From 434305a6c293f3f32479f1dd2e77291d912872e6 Mon Sep 17 00:00:00 2001 From: Armon Dadgar Date: Mon, 27 Apr 2015 14:20:28 -0700 Subject: [PATCH] secret/aws: Using roles instead of policy --- builtin/logical/aws/backend.go | 4 +- builtin/logical/aws/backend_test.go | 8 ++-- .../aws/{path_policy.go => path_roles.go} | 32 ++++++------- builtin/logical/aws/path_user.go | 12 ++--- website/source/docs/secrets/aws/index.html.md | 47 ++++++++++--------- 5 files changed, 53 insertions(+), 50 deletions(-) rename builtin/logical/aws/{path_policy.go => path_roles.go} (74%) diff --git a/builtin/logical/aws/backend.go b/builtin/logical/aws/backend.go index 09d69d99f..dd471ee23 100644 --- a/builtin/logical/aws/backend.go +++ b/builtin/logical/aws/backend.go @@ -26,7 +26,7 @@ func Backend() *framework.Backend { Paths: []*framework.Path{ pathConfigRoot(), pathConfigLease(&b), - pathPolicy(), + pathRoles(), pathUser(&b), }, @@ -52,5 +52,5 @@ are automatically revoked at the end of the lease. After mounting this backend, credentials to generate IAM keys must be configured with the "root" path and policies must be written using -the "policy/" endpoints before any access keys can be generated. +the "roles/" endpoints before any access keys can be generated. ` diff --git a/builtin/logical/aws/backend_test.go b/builtin/logical/aws/backend_test.go index 7924d2bf9..796feb918 100644 --- a/builtin/logical/aws/backend_test.go +++ b/builtin/logical/aws/backend_test.go @@ -76,7 +76,7 @@ func testAccStepConfig(t *testing.T) logicaltest.TestStep { func testAccStepReadUser(t *testing.T, name string) logicaltest.TestStep { return logicaltest.TestStep{ Operation: logical.ReadOperation, - Path: name, + Path: "creds/" + name, Check: func(resp *logical.Response) error { var d struct { AccessKey string `mapstructure:"access_key"` @@ -109,7 +109,7 @@ func testAccStepReadUser(t *testing.T, name string) logicaltest.TestStep { func testAccStepWritePolicy(t *testing.T, name string, policy string) logicaltest.TestStep { return logicaltest.TestStep{ Operation: logical.WriteOperation, - Path: "policy/" + name, + Path: "roles/" + name, Data: map[string]interface{}{ "policy": testPolicy, }, @@ -119,14 +119,14 @@ func testAccStepWritePolicy(t *testing.T, name string, policy string) logicaltes func testAccStepDeletePolicy(t *testing.T, n string) logicaltest.TestStep { return logicaltest.TestStep{ Operation: logical.DeleteOperation, - Path: "policy/" + n, + Path: "roles/" + n, } } func testAccStepReadPolicy(t *testing.T, name string, value string) logicaltest.TestStep { return logicaltest.TestStep{ Operation: logical.ReadOperation, - Path: "policy/" + name, + Path: "roles/" + name, Check: func(resp *logical.Response) error { if resp == nil { if value == "" { diff --git a/builtin/logical/aws/path_policy.go b/builtin/logical/aws/path_roles.go similarity index 74% rename from builtin/logical/aws/path_policy.go rename to builtin/logical/aws/path_roles.go index 2e77cb768..06dfab8ac 100644 --- a/builtin/logical/aws/path_policy.go +++ b/builtin/logical/aws/path_roles.go @@ -9,9 +9,9 @@ import ( "github.com/hashicorp/vault/logical/framework" ) -func pathPolicy() *framework.Path { +func pathRoles() *framework.Path { return &framework.Path{ - Pattern: `policy/(?P\w+)`, + Pattern: `roles/(?P\w+)`, Fields: map[string]*framework.FieldSchema{ "name": &framework.FieldSchema{ Type: framework.TypeString, @@ -25,17 +25,17 @@ func pathPolicy() *framework.Path { }, Callbacks: map[logical.Operation]framework.OperationFunc{ - logical.DeleteOperation: pathPolicyDelete, - logical.ReadOperation: pathPolicyRead, - logical.WriteOperation: pathPolicyWrite, + logical.DeleteOperation: pathRolesDelete, + logical.ReadOperation: pathRolesRead, + logical.WriteOperation: pathRolesWrite, }, - HelpSynopsis: pathPolicyHelpSyn, - HelpDescription: pathPolicyHelpDesc, + HelpSynopsis: pathRolesHelpSyn, + HelpDescription: pathRolesHelpDesc, } } -func pathPolicyDelete( +func pathRolesDelete( req *logical.Request, d *framework.FieldData) (*logical.Response, error) { err := req.Storage.Delete("policy/" + d.Get("name").(string)) if err != nil { @@ -45,7 +45,7 @@ func pathPolicyDelete( return nil, nil } -func pathPolicyRead( +func pathRolesRead( req *logical.Request, d *framework.FieldData) (*logical.Response, error) { entry, err := req.Storage.Get("policy/" + d.Get("name").(string)) if err != nil { @@ -62,7 +62,7 @@ func pathPolicyRead( }, nil } -func pathPolicyWrite( +func pathRolesWrite( req *logical.Request, d *framework.FieldData) (*logical.Response, error) { var buf bytes.Buffer if err := json.Compact(&buf, []byte(d.Get("policy").(string))); err != nil { @@ -82,16 +82,16 @@ func pathPolicyWrite( return nil, nil } -const pathPolicyHelpSyn = ` +const pathRolesHelpSyn = ` Read and write IAM policies that access keys can be made for. ` -const pathPolicyHelpDesc = ` -This path allows you to read and write policies that are used to -create access keys. These policies map directly to the route to read the +const pathRolesHelpDesc = ` +This path allows you to read and write roles that are used to +create access keys. These roles have IAM policies that map directly to the route to read the access keys. For example, if the backend is mounted at "aws" and you -wrote a policy to "aws/policy/deploy" then a user could request access -credentials at "aws/deploy". +create a role at "aws/roles/deploy" then a user could request access +credentials at "aws/creds/deploy". The policies written are normal IAM policies. Vault will not attempt to parse these except to validate that they're basic JSON. To validate the diff --git a/builtin/logical/aws/path_user.go b/builtin/logical/aws/path_user.go index 363f682a2..007ca6a2b 100644 --- a/builtin/logical/aws/path_user.go +++ b/builtin/logical/aws/path_user.go @@ -12,11 +12,11 @@ import ( func pathUser(b *backend) *framework.Path { return &framework.Path{ - Pattern: `(?P\w+)`, + Pattern: `creds/(?P\w+)`, Fields: map[string]*framework.FieldSchema{ "name": &framework.FieldSchema{ Type: framework.TypeString, - Description: "Name of the policy", + Description: "Name of the role", }, }, @@ -36,11 +36,11 @@ func (b *backend) pathUserRead( // Read the policy policy, err := req.Storage.Get("policy/" + policyName) if err != nil { - return nil, fmt.Errorf("error retrieving policy: %s", err) + return nil, fmt.Errorf("error retrieving role: %s", err) } if policy == nil { return logical.ErrorResponse(fmt.Sprintf( - "Policy '%s' not found", policyName)), nil + "Role '%s' not found", policyName)), nil } // Use the helper to create the secret @@ -138,14 +138,14 @@ type walUser struct { } const pathUserHelpSyn = ` -Generate an access key pair for a specific policy. +Generate an access key pair for a specific role. ` const pathUserHelpDesc = ` This path will generate a new, never before used key pair for accessing AWS. The IAM policy used to back this key pair will be the "name" parameter. For example, if this backend is mounted at "aws", -then "aws/deploy" would generate access keys for the "deploy" policy. +then "aws/creds/deploy" would generate access keys for the "deploy" role. The access keys will have a lease associated with them. The access keys can be revoked by using the lease ID. diff --git a/website/source/docs/secrets/aws/index.html.md b/website/source/docs/secrets/aws/index.html.md index 6a006111d..bf233cff6 100644 --- a/website/source/docs/secrets/aws/index.html.md +++ b/website/source/docs/secrets/aws/index.html.md @@ -20,14 +20,15 @@ on every path, use `vault help` after mounting the backend. ## Quick Start -Mount the aws secret backend using the `vault mount` command: +The first step to using the aws backend is to mount it. +Unlike the `generic` backend, the `aws` backend is not mounted by default. ```text $ vault mount aws Successfully mounted 'aws' at 'aws'! ``` -Configure the root credentials that are used to manage IAM credentials: +Next, we must configure the root credentials that are used to manage IAM credentials: ```text $ vault write aws/config/root \ @@ -44,17 +45,19 @@ The following parameters are required: credentials. - `region` the AWS region for API calls. -Create an IAM policy: +The next step is to configure a role. A role is a logical name that maps +to a policy used to generated those credentials. For example, lets create +a "deploy" role: ```text -$ vault write aws/policy/deploy \ +$ vault write aws/roles/deploy \ name=deploy \ policy=@policy.json ``` -This path will generate a new, never before used key pair for -accessing AWS. The IAM policy used to back this key pair will be -the "name" parameter, which is "deploy" in this example. +This path will create a named role along with the IAM policy used +to restrict permissions for it. This is used to dynamically create +a new pair of IAM credentials when needed. The `@` tells Vault to load the policy from the file named `policy.json`. Here is an example IAM policy to get started: @@ -73,12 +76,12 @@ is an example IAM policy to get started: For more information on IAM policies, please see the [AWS IAM policy documentation](http://docs.aws.amazon.com/IAM/latest/UserGuide/PoliciesOverview.html). -Vault can now generate IAM credentials under the given policy: +To generate a new set of IAM credentials, we simply read from that role: ```text -$ vault read aws/deploy +$ vault read aws/creds/deploy Key Value -lease_id aws/deploy/7cb8df71-782f-3de1-79dd-251778e49f58 +lease_id aws/creds/deploy/7cb8df71-782f-3de1-79dd-251778e49f58 lease_duration 3600 access_key AKIAIOMYUTSLGJOGLHTQ secret_key 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 @@ -87,9 +90,9 @@ secret_key BK9++oBABaBvRKcT5KEF69xQGcH7ZpPRF3oqVEv7 If you run the command again, you will get a new set of credentials: ```text -$ vault read aws/deploy +$ vault read aws/creds/deploy Key Value -lease_id aws/deploy/82d89562-ff19-382e-6be9-cb45c8f6a42d +lease_id aws/creds/deploy/82d89562-ff19-382e-6be9-cb45c8f6a42d lease_duration 3600 access_key AKIAJZ5YRPHFH3QHRRRQ secret_key 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 @@ -183,20 +186,20 @@ interactive help output. -### /aws/policy/ +### /aws/roles/ #### POST
Description
- Creates or updates a named policy. + Creates or updates a named role.
Method
POST
URL
-
`/aws/policy/`
+
`/aws/roles/`
Parameters
@@ -220,14 +223,14 @@ interactive help output.
Description
- Queries a named policy. + Queries a named role.
Method
GET
URL
-
`/aws/policy/`
+
`/aws/roles/`
Parameters
@@ -253,14 +256,14 @@ interactive help output.
Description
- Deletes a named policy. + Deletes a named role.
Method
DELETE
URL
-
`/aws/policy/`
+
`/aws/roles/`
Parameters
@@ -274,20 +277,20 @@ interactive help output.
-### /aws/ +### /aws/creds/ #### GET
Description
- Generates a dynamic IAM credential based on the named policy. + Generates a dynamic IAM credential based on the named role.
Method
GET
URL
-
`/aws/`
+
`/aws/creds/`
Parameters