Skip to main content

Managing Cloud Credentials

Cloud credentials allow OpenPrime to interact with your cloud providers for deploying infrastructure.

Security Model​

Credentials are:

  • Encrypted at rest using AES-256-GCM
  • User-scoped - each user manages their own credentials
  • Never logged - sensitive values are masked in logs

Adding Credentials​

AWS Credentials​

  1. Navigate to Settings → Cloud Credentials
  2. Click Add Credential → AWS
  3. Enter:
    • Name: Descriptive identifier
    • Access Key ID: Your AWS access key
    • Secret Access Key: Your AWS secret key
    • Default Region: Primary region
{
"provider": "aws",
"name": "production-aws",
"accessKeyId": "AKIA...",
"secretAccessKey": "...",
"defaultRegion": "us-east-1"
}

IAM Policy Requirements​

Two separate things need permissions, and it is easy to grant only the first:

  1. Provisioning your infrastructure — what the generated Terraform applies.
  2. Creating the Terraform state backend — the S3 bucket OpenPrime creates for you before any Terraform runs.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Provisioning",
"Effect": "Allow",
"Action": [
"eks:*",
"ec2:*",
"iam:*",
"autoscaling:*",
"elasticloadbalancing:*"
],
"Resource": "*"
},
{
"Sid": "StateBackendBucket",
"Effect": "Allow",
"Action": [
"s3:CreateBucket",
"s3:ListBucket",
"s3:GetBucketTagging",
"s3:PutBucketTagging",
"s3:PutEncryptionConfiguration",
"s3:PutBucketVersioning",
"s3:PutBucketPublicAccessBlock"
],
"Resource": "arn:aws:s3:::*"
},
{
"Sid": "StateObjects",
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
"Resource": "arn:aws:s3:::*/*"
}
]
}
The state backend needs its own permissions

Without the s3: statements above, creating an environment's state backend fails before Terraform is ever invoked. A policy covering only eks/ec2/iam looks sufficient and is not.

No DynamoDB permissions are needed

Terraform state is locked with S3 native locking — the generated backend block contains use_lockfile = true and no dynamodb_table, and locks appear as .tflock objects beside the state file. The s3:PutObject / s3:DeleteObject grants above already cover them.

Earlier versions of this page listed dynamodb:CreateTable, dynamodb:DescribeTable and dynamodb:DeleteTable as required. They were not, and granting them was unnecessary privilege. A DynamoDB code path still exists in StateCraft for callers that request lockingMechanism: "dynamodb" explicitly through the API; the wizard never does — it sends "s3".

The statements above are exactly the S3 calls StateCraft makes: CreateBucket, PutBucketVersioning, PutBucketEncryption, PutPublicAccessBlock, PutBucketTagging, plus HeadBucket and GetBucketTagging for the ownership checks.

Deleting an environment​

Tearing down a state backend needs more than creating one, because the bucket is versioned and every version has to be removed before it will delete. Add these only if you want OpenPrime to be able to destroy backends:

{
"Effect": "Allow",
"Action": [
"s3:DeleteBucket",
"s3:ListBucketVersions",
"s3:DeleteObjectVersion"
],
"Resource": "*"
}
Scope these down for production

"Resource": "*" keeps the example readable. In a real account, restrict the S3 statements to the bucket name you configure for the backend, which OpenPrime derives as <account-id>-terraform-<environment>.

Deleting an environment does not delete its state bucket

The bucket survives teardown by design — losing state is worse than keeping an empty bucket. Nothing in the product offers to remove it, so a long-lived account accumulates one bucket per environment ever created.

Azure Credentials​

  1. Click Add Credential → Azure
  2. Enter:
    • Name: Descriptive identifier
    • Subscription ID: Your Azure subscription
    • Tenant ID: Azure AD tenant
    • Client ID: Service principal app ID
    • Client Secret: Service principal secret
{
"provider": "azure",
"name": "production-azure",
"subscriptionId": "...",
"tenantId": "...",
"clientId": "...",
"clientSecret": "..."
}

GCP Credentials​

  1. Click Add Credential → GCP
  2. Upload or paste service account JSON:
{
"provider": "gcp",
"name": "production-gcp",
"projectId": "my-project",
"serviceAccountKey": { ... }
}

Using Credentials​

Assigning to Environments​

When creating/editing an environment:

  1. Select the Cloud Credential dropdown
  2. Choose the appropriate credential
  3. Credential is referenced, not copied

Generated Code​

Credentials are referenced in generated Terraform:

# AWS provider
provider "aws" {
region = var.aws_region
# Credentials via environment variables
}

Set environment variables when running Terraform:

export AWS_ACCESS_KEY_ID="..."
export AWS_SECRET_ACCESS_KEY="..."
terraform apply

Credential Rotation​

Updating Credentials​

  1. Navigate to Settings → Cloud Credentials
  2. Click Edit on the credential
  3. Update the secret values
  4. Save changes

Existing environments using this credential will use new values on next deployment.

Best Practices​

  • Rotate regularly - Every 90 days recommended
  • Use least privilege - Minimal permissions needed
  • Separate by environment - Production vs. development
  • Monitor usage - Enable CloudTrail/Activity Logs

Troubleshooting​

"Invalid credentials" Error​

  1. Verify credentials are correct
  2. Check IAM permissions
  3. Ensure region is correct
  4. Test with AWS CLI:
aws sts get-caller-identity

Credentials Not Listed​

  1. Refresh the page
  2. Check browser console for errors
  3. Verify you're logged in as correct user