Skip to content

Commit

Permalink
Merge pull request #58 from PierreBeucher/aws-se
Browse files Browse the repository at this point in the history
feat: AWS Secret Engine
  • Loading branch information
Haennetz authored Feb 27, 2024
2 parents 5ea9f8f + 809de3e commit 34e3874
Show file tree
Hide file tree
Showing 9 changed files with 783 additions and 4 deletions.
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ The following features are currently supported:
- [Token](https://www.vaultproject.io/docs/auth/token)
- [Userpass](https://www.vaultproject.io/docs/auth/userpass)
- Secrets
- [AWS](https://developer.hashicorp.com/vault/docs/secrets/aws)
- [Databases](https://www.vaultproject.io/api-docs/secret/databases)
- [KV v1](https://www.vaultproject.io/docs/secrets/kv/kv-v1)
- [KV v2](https://www.vaultproject.io/docs/secrets/kv/kv-v2)
Expand Down Expand Up @@ -92,6 +93,40 @@ let client = VaultClient::new(

### Secrets

#### AWS

The library currently supports all operations available for the
AWS Secret Engine.

See [tests/aws.rs](./tests/aws.rs) for more examples.

```rust
// Mount AWS SE
server.mount_secret(client, path, "aws").await?;
let endpoint = AwsSecretEngineEndpoint { path: path }

// Configure AWS SE
aws::config::set(client, &endpoint.path, "access_key", "secret_key", Some(SetConfigurationRequest::builder()
.max_retries(3)
.region("eu-central-1")
)).await?,

// Create HVault role
aws::roles::create_update(client, &endpoint.path, "my_role", "assumed_role", Some(CreateUpdateRoleRequest::builder()
.role_arns( vec!["arn:aws:iam::123456789012:role/test_role"] )
)).await?

// Generate credentials
let res = aws::roles::credentials(client, &endpoint.path, "my_role", Some(GenerateCredentialsRequest::builder()
.ttl("3h")
)).await?;

let creds = res.unwrap();
// creds.access_key
// creds.secret_key
// creds.security_token
```

#### Key Value v2

The library currently supports all operations available for version 2 of the
Expand Down
1 change: 1 addition & 0 deletions src/api.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod auth;
pub mod aws;
pub mod database;
pub mod kv1;
pub mod kv2;
Expand Down
2 changes: 2 additions & 0 deletions src/api/aws.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod requests;
pub mod responses;
262 changes: 262 additions & 0 deletions src/api/aws/requests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
use rustify_derive::Endpoint;
use std::fmt::Debug;

use super::responses::{
GenerateCredentialsResponse, GetConfigurationResponse, ListRolesResponse, ReadLeaseResponse,
ReadRoleResponse, RotateRootCredentialsResponse,
};

/// ## Configure Root IAM Credentials
///
/// Configures the root IAM credentials to communicate with AWS.
///
/// * Path: {self.mount}/config/root
/// * Method: POST
/// * Response: N/A
/// * Reference: https://developer.hashicorp.com/vault/api-docs/secret/aws#configure-root-iam-credentials
#[derive(Builder, Debug, Default, Endpoint)]
#[endpoint(path = "{self.mount}/config/root", method = "POST", builder = "true")]
#[builder(setter(into, strip_option), default)]
pub struct SetConfigurationRequest {
#[endpoint(skip)]
pub mount: String,
pub max_retries: Option<i32>,
pub access_key: String,
pub secret_key: String,
pub region: Option<String>,
pub iam_endpoint: Option<String>,
pub sts_endpoint: Option<String>,
pub username_template: Option<String>,
}

/// ## Read Root Configuration
///
/// Read non-secure values that have been configured in the config/root endpoint
///
/// * Path: {self.mount}/config/root
/// * Method: GET
/// * Response: [GetConfigurationResponse]
/// * Reference: https://developer.hashicorp.com/vault/api-docs/secret/aws#read-root-configuration
#[derive(Builder, Debug, Default, Endpoint)]
#[endpoint(
path = "{self.mount}/config/root",
method = "GET",
builder = "true",
response = "GetConfigurationResponse"
)]
#[builder(setter(into, strip_option), default)]
pub struct GetConfigurationRequest {
#[endpoint(skip)]
pub mount: String,
}

/// ## Rotate Root IAM Credentials
///
/// When you have configured Vault with static credentials, you can use this endpoint to have Vault rotate the access key it used.
///
/// * Path: {self.mount}/config/rotate-root
/// * Method: GET
/// * Response: [RotateRootCredentialsResponse]
/// * Reference: https://developer.hashicorp.com/vault/api-docs/secret/aws#rotate-root-iam-credentials
#[derive(Builder, Debug, Default, Endpoint)]
#[endpoint(
path = "{self.mount}/config/rotate-root",
method = "POST",
builder = "true",
response = "RotateRootCredentialsResponse"
)]
#[builder(setter(into, strip_option), default)]
pub struct RotateRootCredentialsRequest {
#[endpoint(skip)]
pub mount: String,
}

/// ## Configure Lease
///
/// Configures lease settings for the AWS secrets engine
///
/// * Path: {self.mount}/config/lease
/// * Method: POST
/// * Response: N.A.
/// * Reference: https://developer.hashicorp.com/vault/api-docs/secret/aws#configure-lease
#[derive(Builder, Debug, Default, Endpoint)]
#[endpoint(path = "{self.mount}/config/lease", method = "POST", builder = "true")]
#[builder(setter(into, strip_option), default)]
pub struct ConfigureLeaseRequest {
#[endpoint(skip)]
pub mount: String,

pub lease: String,
pub lease_max: String,
}

/// ## Read Lease
///
/// Returns the current lease settings for the AWS secrets engine
///
/// * Path: {self.mount}/config/lease
/// * Method: GET
/// * Response: [ReadLeaseResponse]
/// * Reference: https://developer.hashicorp.com/vault/api-docs/secret/aws#read-lease
#[derive(Builder, Debug, Default, Endpoint)]
#[endpoint(
path = "{self.mount}/config/lease",
method = "GET",
response = "ReadLeaseResponse",
builder = "true"
)]
#[builder(setter(into, strip_option), default)]
pub struct ReadLeaseRequest {
#[endpoint(skip)]
pub mount: String,
}

/// ## Create/Update Role
///
/// Creates or updates the role with the given name
///
/// * Path: {self.mount}/roles/{self.name}
/// * Method: POST
/// * Response: N.A.
/// * Reference: https://developer.hashicorp.com/vault/api-docs/secret/aws#create-update-role
#[derive(Builder, Debug, Default, Endpoint)]
#[endpoint(
path = "{self.mount}/roles/{self.name}",
method = "POST",
builder = "true"
)]
#[builder(setter(into, strip_option), default)]
pub struct CreateUpdateRoleRequest {
#[endpoint(skip)]
pub mount: String,

pub name: String,
pub credential_type: String,
pub role_arns: Option<Vec<String>>,
pub policy_arns: Option<Vec<String>>,
pub policy_document: String,
pub iam_groups: Option<Vec<String>>,
pub iam_tags: Option<Vec<String>>,
pub default_sts_ttl: Option<u32>,
pub max_sts_ttl: Option<u32>,
pub user_path: Option<String>,
pub permissions_boundary_arn: Option<String>,

pub policy: Option<String>,
pub arn: Option<String>,
}

/// ## Read Role
///
/// Queries an existing role by the given name
///
/// * Path: {self.mount}/roles/{self.name}
/// * Method: GET
/// * Response: [ReadRoleResponse]
/// * Reference: https://developer.hashicorp.com/vault/api-docs/secret/aws#read-role
#[derive(Builder, Debug, Default, Endpoint)]
#[endpoint(
path = "{self.mount}/roles/{self.name}",
method = "GET",
response = "ReadRoleResponse",
builder = "true"
)]
#[builder(setter(into, strip_option), default)]
pub struct ReadRoleRequest {
#[endpoint(skip)]
pub mount: String,

pub name: String,
}

/// ## List Roles
///
/// lists all existing roles in the secrets engine
///
/// * Path: {self.mount}/roles
/// * Method: LIST
/// * Response: [ListRolesResponse]
/// * Reference: https://developer.hashicorp.com/vault/api-docs/secret/aws#list-roles
#[derive(Builder, Debug, Default, Endpoint)]
#[endpoint(
path = "{self.mount}/roles",
method = "LIST",
response = "ListRolesResponse",
builder = "true"
)]
#[builder(setter(into, strip_option), default)]
pub struct ListRolesRequest {
#[endpoint(skip)]
pub mount: String,
}

/// ## Delete Role
///
/// Deletes an existing role by the given name
///
/// * Path: {self.mount}/roles/{self.name}
/// * Method: DELETE
/// * Response: N.A.
/// * Reference: https://developer.hashicorp.com/vault/api-docs/secret/aws#delete-role
#[derive(Builder, Debug, Default, Endpoint)]
#[endpoint(
path = "{self.mount}/roles/{self.name}",
method = "DELETE",
builder = "true"
)]
#[builder(setter(into, strip_option), default)]
pub struct DeleteRoleRequest {
#[endpoint(skip)]
pub mount: String,
pub name: String,
}

/// ## Generate Credentials (/aws/creds)
///
/// Generates credentials based on the named role using /aws/creds endpoint
///
/// * Path: {self.mount}/creds/{self.name}
/// * Method: GET
/// * Response: [GenerateCredentialsResponse]
/// * Reference: https://developer.hashicorp.com/vault/api-docs/secret/aws#generate-credentials
#[derive(Builder, Debug, Default, Endpoint)]
#[endpoint(
path = "{self.mount}/creds/{self.name}",
method = "GET",
response = "GenerateCredentialsResponse",
builder = "true"
)]
#[builder(setter(into, strip_option), default)]
pub struct GenerateCredentialsRequest {
#[endpoint(skip)]
pub mount: String,
pub name: String,
pub role_arn: Option<String>,
pub role_session_name: Option<String>,
pub ttl: Option<String>,
}

/// ## Generate Credentials (/aws/sts)
///
/// Generates credentials based on the named role using /aws/sts endpoint
///
/// * Path: {self.mount}/sts/{self.name}
/// * Method: POST
/// * Response: [GenerateCredentialsResponse]
/// * Reference: https://developer.hashicorp.com/vault/api-docs/secret/aws#generate-credentials
#[derive(Builder, Debug, Default, Endpoint)]
#[endpoint(
path = "{self.mount}/sts/{self.name}",
method = "POST",
response = "GenerateCredentialsResponse",
builder = "true"
)]
#[builder(setter(into, strip_option), default)]
pub struct GenerateCredentialsStsRequest {
#[endpoint(skip)]
pub mount: String,
pub name: String,
pub role_arn: Option<String>,
pub role_session_name: Option<String>,
pub ttl: Option<String>,
}
56 changes: 56 additions & 0 deletions src/api/aws/responses.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use serde::{Deserialize, Serialize};

/// Response from executing
/// [GetConfigurationRequest][crate::api::aws::requests::GetConfigurationRequest]
#[derive(Deserialize, Debug, Serialize)]
pub struct GetConfigurationResponse {
pub access_key: String,
pub region: String,
pub iam_endpoint: String,
pub sts_endpoint: String,
pub max_retries: u32,
}

/// Response from executing
/// [RotateRootCredentialsRequest][crate::api::aws::requests::RotateRootCredentialsRequest]
#[derive(Deserialize, Debug, Serialize)]
pub struct RotateRootCredentialsResponse {
pub access_key: String,
}

/// Response from executing
/// [ReadLeaseRequest][crate::api::aws::requests::ReadLeaseRequest]
#[derive(Deserialize, Debug, Serialize)]
pub struct ReadLeaseResponse {
pub lease: String,
pub lease_max: String,
}

/// Response from executing
/// [ReadRoleRequest][crate::api::aws::requests::ReadRoleRequest]
#[derive(Deserialize, Debug, Serialize)]
pub struct ReadRoleResponse {
pub policy_document: Option<String>,
pub policy_arns: Option<Vec<String>>,
pub credential_type: String,
pub role_arns: Option<Vec<String>>,
pub iam_groups: Option<Vec<String>>,
}

/// Response from executing
/// [ListRolesRequest][crate::api::aws::requests::ListRolesRequest]
#[derive(Deserialize, Debug, Serialize)]
pub struct ListRolesResponse {
pub keys: Vec<String>,
}

/// Response from executing
/// [GenerateCredentialsRequest][crate::api::aws::requests::GenerateCredentialsRequest]
#[derive(Deserialize, Debug, Serialize)]
pub struct GenerateCredentialsResponse {
pub access_key: String,
pub secret_key: String,
pub security_token: Option<String>,
pub arn: String,
}
Loading

0 comments on commit 34e3874

Please sign in to comment.