AWS OIDC - DeployService: configure IAM#28088
Conversation
264fdef to
3c0d30d
Compare
a57099f to
1ca17fd
Compare
1ca17fd to
4ca207d
Compare
| Resources SliceOrString `json:"Resource"` | ||
| Resources SliceOrString `json:"Resource,omitempty"` | ||
| // Principals is a list of principals. | ||
| Principals map[string]SliceOrString `json:"Principal,omitempty"` |
There was a problem hiding this comment.
| Principals map[string]SliceOrString `json:"Principal,omitempty"` | |
| Principal map[string]SliceOrString `json:"Principal,omitempty"` |
There was a problem hiding this comment.
I was trying to be consistent with the fields above
They use plural form but then the json tag is singular
Should we change them to singular as well? Resource and Action vs Resources and Actions
There was a problem hiding this comment.
Oh, I haven't notice this. Lets ignore my comment and keep this constant.
|
|
||
| joinOpenSSH.Flag("debug", "Enable verbose logging to stderr.").Short('d').BoolVar(&ccf.Debug) | ||
|
|
||
| integrationCmd := app.Command("integration", "Integration commands") |
There was a problem hiding this comment.
The integration is quite generic but what is the difference between :
-- teleprot discovery bootstrap
-- db configure bootstrap
Do we need to introduce new patter for the deployservice-iam service.
Can we just create teleport deployservice-iam bootstrap/configure commands ?
There was a problem hiding this comment.
This is not (yet) discovery related.
It only installs a DatabaseService in Amazon ECS for the proxy.
We can, yeah
We might have other configuration needs when setting up the IAM requirements for other integrations and I was trying to create an abstraction/layer for them. So that they don't pollute the top level teleport commands
992f3be to
79ed5c9
Compare
|
Friendly ping @smallinsky @gabrielcorado @greedy52 🙏 |
smallinsky
left a comment
There was a problem hiding this comment.
Left some nit comments but mostly LGTM.
| Resources SliceOrString `json:"Resource"` | ||
| Resources SliceOrString `json:"Resource,omitempty"` | ||
| // Principals is a list of principals. | ||
| Principals map[string]SliceOrString `json:"Principal,omitempty"` |
There was a problem hiding this comment.
Oh, I haven't notice this. Lets ignore my comment and keep this constant.
| func (d awsTags) ToIAMTags() []iamTypes.Tag { | ||
| iamTags := make([]iamTypes.Tag, 0, len(d)) | ||
| for k, v := range d { | ||
| k, v := k, v |
There was a problem hiding this comment.
Key and Value of d awsTags[map[string]string are "value" types. Why do we need make a second copy ?
There was a problem hiding this comment.
But then we use their address because iamTypes.Tag.Key/Value require string pointers.
I just removed the second copy and the tests in tags_test.go fail because of it
There was a problem hiding this comment.
i think they will fix this in newer go, eventually
https://github.com/golang/go/wiki/LoopvarExperiment.
An alternative is to use aws.String() instead of &k/&v that takes care of the copy through function call
| } | ||
|
|
||
| // PolicyARN returns the ARN representation of an AWS IAM Policy. | ||
| func PolicyARN(partition, accountID, policy string) string { |
There was a problem hiding this comment.
Nit: maybe a good place to put these functions is lib/utils/aws/aws.go. There are some similar functions, but for the IAM role and user.
There was a problem hiding this comment.
awsapiutils "github.com/gravitational/teleport/api/utils/aws"
awslib "github.com/gravitational/teleport/lib/cloud/aws"
awslibutils "github.com/gravitational/teleport/lib/utils/aws"
🥵
| } | ||
|
|
||
| // NewDeployServiceIAMConfigureClient creates a new DeployServiceIAMConfigureClient. | ||
| func NewDeployServiceIAMConfigureClient(ctx context.Context, region string) (DeployServiceIAMConfigureClient, error) { |
There was a problem hiding this comment.
A question that might be outside this PR scope: What about using the already existing cloud clients for getting AWS clients? It already initializes the connection (I know the db configurator does not rely on it too, but there is no reason not to use it). The good thing is that AWS already supports some good options, like cross-account clients, and already has a test implementation. That would also help us get everything to use the same SDK major version.
There was a problem hiding this comment.
My 2c on this, we should really move to v2. I submitted a small request in v1 a few months ago. They rejected and ask me to request it in v2. Maybe we should start a cloud.ClientsV2.
There was a problem hiding this comment.
Yeah, I really wanted to use V2 here
I could create the same abstraction for V2, but that seemed to be overkill for this PR
| // StatementForRDSDBConnect returns a statement that allows the `rds-db:connect` for all RDS DBs. | ||
| func StatementForRDSDBConnect() *Statement { | ||
| return &Statement{ | ||
| Effect: EffectAllow, | ||
| Actions: SliceOrString{"rds-db:connect"}, | ||
| Resources: allResources, | ||
| } | ||
| } |
There was a problem hiding this comment.
is there plan to support other DB types of deploy service? if so, ideally can share this with the db actions listed in configurators/aws. I guess we can refactor when that days comes too =D.
There was a problem hiding this comment.
We will probably have more in the future 👍
There's indeed some duplication that we should get rid off.
Let's see how the DeployService evolves and then centralize all these statements.
| if trace.IsAlreadyExists(awslib.ConvertIAMv2Error(err)) { | ||
| return trace.AlreadyExists("Role %q already exists, please remove it and try again.", req.TaskRole) | ||
| } | ||
| return trace.Wrap(err) |
There was a problem hiding this comment.
should here return the converted type?
There was a problem hiding this comment.
I wanted to change the message so that it includes an action to resolve the issue ("remove it").
This way, the user can fix it.
If I return the converted type, then it will be the raw AWS error message.
There was a problem hiding this comment.
i meant the return trace.Wrap(err) after the already exist check (like return trace.Wrap(the-converted-error). I guess not big difference.
There was a problem hiding this comment.
Oh right 🙏
Yes! changing
| } | ||
|
|
||
| _, err = clt.PutRolePolicy(ctx, &iam.PutRolePolicyInput{ | ||
| PolicyName: &req.IntegrationRoleDeployServicePolicy, |
There was a problem hiding this comment.
Can an intergration role used for multiple task roles? if so, the policy names will collide.
There was a problem hiding this comment.
We might need to change this when we have multiple Deployment Modes.
For now, there's only database-service so they should not collide.
I'll make sure to add a suffix when we add a policy for another deployment.
Or we might have this policy always having the set of required statements for the deployments we have
79ed5c9 to
279b9c6
Compare
|
@marcoandredinis See the table below for backport results.
|
* auto configure deployservice iam * review pt1 * review pt2
DeployService allows the user to deploy a Database Service (other services will be available later on) in a single click.
You can read more about it here:
#27035
#25521 (comment)
The IAM set up consists of:
It's quite tedious and error prone.
Instead of giving users a detailed guide on how to set this up, we will ask users to run this command on their machine or Amazon CloudShell.
They must have the following permission to be able to run the configuration command:
The script does not try to be smart:
We can add more checks to ensure a better UX, but we decided to keep things simple and safe for now.
If you think otherwise, please let me know.
Demo:
Running the script again, returns an error indicating that the policy (used as Task Role Boundary) already exists
If the IntegrationRole does not exist: