Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
201 changes: 196 additions & 5 deletions documentation/docs/getting-started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,202 @@ s3:
```

:::info
Instead of using access keys it is possible to use **IAM roles** for more fine grained access management. To achieve that set in your helm values

1. `s3.authType` to `aws-irsa`, and
2. `s3.awsStsEndpoint` to your desired region (`https://sts.REGION.amazonaws.com`).
:::
Instead of using access keys, it is possible to use [EKS Pod Identities](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html) or [IRSA](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) in secureCodeBox to authenticate to the S3 bucket using short-lived, automatically rotated credentials.

However, because these credentials are short-lived (maximum lifetime of 12 hours), scans started by the operator in this setup are limited in their maximum duration. The tokens are automatically rotated when they reach 20% of their remaining lifetime. This means:

- In the worst-case scenario, a scan might start right before a token rotation occurs
- At this point, the current token has approximately 2.4 hours remaining (20% of 12 hours)
- The scan will use this current token for its entire duration
- If the scan runs longer than 2.4 hours, it will complete successfully but fail when attempting to save results to S3 because the token has expired

Therefore, scans must complete within 2.4 hours to ensure results can be persisted to S3. Depending on the expected scan duration in your setup, this limitation can pose a problem. See: [Issue secureCodeBox/secureCodeBox#2255](https://github.com/secureCodeBox/secureCodeBox/issues/2255)

<details>
<summary>Example Pod Identity Setup (recommended over IRSA)</summary>

Terraform/OpenTofu setup for the IAM Role & Policy:
```tf
resource "aws_iam_policy" "securecodebox_s3_policy" {
name = "securecodebox-s3-${var.bucket_name}-access"
description = "IAM policy for secureCodeBox to access S3 bucket ${var.bucket_name}"

policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:GetObjectVersion",
"s3:PutObjectAcl",
"s3:GetObjectAcl"
]
Resource = [
"arn:aws:s3:::${var.bucket_name}/*"
]
},
{
Effect = "Allow"
Action = [
"s3:ListBucket",
"s3:GetBucketLocation",
"s3:GetBucketVersioning"
]
Resource = [
"arn:aws:s3:::${var.bucket_name}"
]
}
]
})
}

# IAM Role for secureCodeBox with EKS Pod Identity
resource "aws_iam_role" "securecodebox_role" {
name = "securecodebox-role"

max_session_duration = 12 * 60 * 60 // 12h, session duration needs to be this long to allow the operator to create presigned urls with a longer lifetime

# Use EKS Pod Identity for the operator service account.
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Service = "pods.eks.amazonaws.com"
}
Action = [
"sts:AssumeRole",
"sts:TagSession"
]
}
]
})
}

# Attach the S3 policy to the role
resource "aws_iam_role_policy_attachment" "securecodebox_s3_policy_attachment" {
role = aws_iam_role.securecodebox_role.name
policy_arn = aws_iam_policy.securecodebox_s3_policy.arn
}

# Create EKS Pod Identity Association
resource "aws_eks_pod_identity_association" "securecodebox_operator" {
cluster_name = var.cluster_name
namespace = "securecodebox-system"
service_account = "securecodebox-operator"
role_arn = aws_iam_role.securecodebox_role.arn
}
```

secureCodeBox Operator values:

```yaml
minio:
enabled: false
s3:
enabled: true
authType: "aws-iam"
bucket: <your-bucket-name>
endpoint: "s3.<your-region>.amazonaws.com"
```
</details>

<details>
<summary>Example IRSA Setup</summary>

Terraform/OpenTofu setup for the IAM Role & Policy:
```tf
resource "aws_iam_policy" "securecodebox_s3_policy" {
name = "securecodebox-s3-${var.bucket_name}-access"
description = "IAM policy for secureCodeBox to access S3 bucket ${var.bucket_name}"

policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:GetObjectVersion",
"s3:PutObjectAcl",
"s3:GetObjectAcl"
]
Resource = [
"arn:aws:s3:::${var.bucket_name}/*"
]
},
{
Effect = "Allow"
Action = [
"s3:ListBucket",
"s3:GetBucketLocation",
"s3:GetBucketVersioning"
]
Resource = [
"arn:aws:s3:::${var.bucket_name}"
]
}
]
})
}

# IAM Role for secureCodeBox with EKS Pod Identity
resource "aws_iam_role" "securecodebox_role" {
name = "securecodebox-role"

max_session_duration = 12 * 60 * 60 // 12h, session duration needs to be this long to allow the operator to create presigned urls with a longer lifetime

# Use IRSA (IAM Roles for Service Accounts) via the cluster OIDC provider.
# The cluster OIDC issuer is available from the data.aws_eks_cluster.cluster data source.
# The Federated principal is the cluster's OIDC provider ARN in the account.
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Federated = "arn:aws:iam::${var.aws_account_id}:oidc-provider/${var.oidc_provider}"
}
Action = "sts:AssumeRoleWithWebIdentity"
Condition = {
StringEquals = {
"${var.oidc_provider}:sub" = "system:serviceaccount:securecodebox-system:securecodebox-operator"
}
}
}
]
})
}

# Attach the S3 policy to the role
resource "aws_iam_role_policy_attachment" "securecodebox_s3_policy_attachment" {
role = aws_iam_role.securecodebox_role.name
policy_arn = aws_iam_policy.securecodebox_s3_policy.arn
}
```

secureCodeBox Operator values:

```yaml
minio:
enabled: false
s3:
enabled: true
authType: "aws-iam"
bucket: <your-bucket-name>
endpoint: "s3.<your-region>.amazonaws.com"
serviceAccount:
annotations:
eks.amazonaws.com/role-arn: <ARN of the IAM Role created by terraform>
```
</details>
:::

#### Google Cloud Storage

Expand Down
4 changes: 2 additions & 2 deletions operator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ helm install securecodebox-operator oci://ghcr.io/securecodebox/helm/operator
| probes.liveness | object | `{"httpGet":{"path":"/healthz","port":"healthchecks"},"initialDelaySeconds":15,"periodSeconds":20}` | Liveness probe configuration |
| probes.readiness | object | `{"httpGet":{"path":"/readyz","port":"healthchecks"},"initialDelaySeconds":5,"periodSeconds":10}` | Readiness probe configuration |
| resources | object | `{"limits":{"cpu":"100m","memory":"30Mi"},"requests":{"cpu":"100m","memory":"20Mi"}}` | CPU/memory resource requests/limits (see: https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/, https://kubernetes.io/docs/tasks/configure-pod-container/assign-cpu-resource/) |
| s3.authType | string | `"access-secret-key"` | Authentication method. Supports access-secret-key (used by most s3 endpoint) and aws-irsa (Used by AWS EKS IAM Role to Kubenetes Service Account Binding. Support for AWS IRSA is considered experimental in the secureCodeBox) |
| s3.awsStsEndpoint | string | `"https://sts.amazonaws.com"` | STS Endpoint used in AWS IRSA Authentication. Change this to the sts endpoint of your aws region. Only used when s3.authType is set to "aws-irsa" |
| s3.authType | string | `"access-secret-key"` | Authentication method. Supports `access-secret-key` (used by most s3 endpoints) and `aws-iam`` (Used by AWS EKS IAM Role to Kubernetes Service Account Binding (IRSA) and EKS Pod Identity Authentication. Support for AWS IRSA is considered experimental in the secureCodeBox) |
| s3.awsStsEndpoint | string | `"https://sts.amazonaws.com"` | STS Endpoint used in AWS IRSA Authentication. Change this to the sts endpoint of your aws region. Only used when s3.authType is set to "aws-iam". Usually not required, even in IRSA or Pod Identity setups as the region gets injected by AWS into the pod. |
| s3.bucket | string | `"my-bucket"` | |
| s3.enabled | bool | `false` | |
| s3.endpoint | string | `"fra1.digitaloceanspaces.com"` | |
Expand Down
9 changes: 7 additions & 2 deletions operator/controllers/execution/scans/scan_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,13 +261,18 @@ func (r *ScanReconciler) initS3Connection() *minio.Client {

var creds *credentials.Credentials

if authType, ok := os.LookupEnv("S3_AUTH_TYPE"); ok && strings.ToLower(authType) == "aws-irsa" {
// todo(v6): remove support for authType = "aws-irsa" and only support "aws-iam": https://github.com/secureCodeBox/secureCodeBox/issues/3327
if authType, ok := os.LookupEnv("S3_AUTH_TYPE"); ok && (strings.ToLower(authType) == "aws-irsa" || strings.ToLower(authType) == "aws-iam") {
stsEndpoint := ""
// todo(v6): remove support for S3_AWS_STS_ENDPOINT env var and only support S3_AWS_IRSA_STS_ENDPOINT: https://github.com/secureCodeBox/secureCodeBox/issues/3327
if configuredStsEndpoint, ok := os.LookupEnv("S3_AWS_IRSA_STS_ENDPOINT"); ok {
stsEndpoint = configuredStsEndpoint
}
if configuredStsEndpoint, ok := os.LookupEnv("S3_AWS_STS_ENDPOINT"); ok {
stsEndpoint = configuredStsEndpoint
}

r.Log.Info("Using AWS IRSA ServiceAccount Bindung for S3 Authentication", "sts", stsEndpoint)
r.Log.Info("Using AWS IAM ServiceAccount Binding for S3 Authentication (IRSA or EKS Pod Identity)", "sts", stsEndpoint)
creds = credentials.NewIAM(stsEndpoint)
} else {
creds = credentials.NewEnvMinio()
Expand Down
4 changes: 2 additions & 2 deletions operator/docs/README.ArtifactHub.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ helm install securecodebox-operator oci://ghcr.io/securecodebox/helm/operator
| probes.liveness | object | `{"httpGet":{"path":"/healthz","port":"healthchecks"},"initialDelaySeconds":15,"periodSeconds":20}` | Liveness probe configuration |
| probes.readiness | object | `{"httpGet":{"path":"/readyz","port":"healthchecks"},"initialDelaySeconds":5,"periodSeconds":10}` | Readiness probe configuration |
| resources | object | `{"limits":{"cpu":"100m","memory":"30Mi"},"requests":{"cpu":"100m","memory":"20Mi"}}` | CPU/memory resource requests/limits (see: https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/, https://kubernetes.io/docs/tasks/configure-pod-container/assign-cpu-resource/) |
| s3.authType | string | `"access-secret-key"` | Authentication method. Supports access-secret-key (used by most s3 endpoint) and aws-irsa (Used by AWS EKS IAM Role to Kubenetes Service Account Binding. Support for AWS IRSA is considered experimental in the secureCodeBox) |
| s3.awsStsEndpoint | string | `"https://sts.amazonaws.com"` | STS Endpoint used in AWS IRSA Authentication. Change this to the sts endpoint of your aws region. Only used when s3.authType is set to "aws-irsa" |
| s3.authType | string | `"access-secret-key"` | Authentication method. Supports `access-secret-key` (used by most s3 endpoints) and `aws-iam`` (Used by AWS EKS IAM Role to Kubernetes Service Account Binding (IRSA) and EKS Pod Identity Authentication. Support for AWS IRSA is considered experimental in the secureCodeBox) |
| s3.awsStsEndpoint | string | `"https://sts.amazonaws.com"` | STS Endpoint used in AWS IRSA Authentication. Change this to the sts endpoint of your aws region. Only used when s3.authType is set to "aws-iam". Usually not required, even in IRSA or Pod Identity setups as the region gets injected by AWS into the pod. |
| s3.bucket | string | `"my-bucket"` | |
| s3.enabled | bool | `false` | |
| s3.endpoint | string | `"fra1.digitaloceanspaces.com"` | |
Expand Down
3 changes: 2 additions & 1 deletion operator/templates/manager/manager.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ spec:
name: {{ .Values.s3.keySecret }}
key: {{ .Values.s3.secretAttributeNames.secretkey }}
{{- end }}
{{- if eq .Values.s3.authType "aws-irsa" }}
# todo(v6): remove support for authType = "aws-irsa" and only support "aws-iam": https://github.com/secureCodeBox/secureCodeBox/issues/3327
{{- if or (eq .Values.s3.authType "aws-irsa") (eq .Values.s3.authType "aws-iam") }}
- name: S3_AWS_IRSA_STS_ENDPOINT
value: {{ .Values.s3.awsStsEndpoint | quote }}
{{- end }}
Expand Down
4 changes: 2 additions & 2 deletions operator/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ s3:
bucket: "my-bucket"
# Implicit 443. You probably only need to change this when the system uses a non default port
port: null
# s3.authType -- Authentication method. Supports access-secret-key (used by most s3 endpoint) and aws-irsa (Used by AWS EKS IAM Role to Kubenetes Service Account Binding. Support for AWS IRSA is considered experimental in the secureCodeBox)
# s3.authType -- Authentication method. Supports `access-secret-key` (used by most s3 endpoints) and `aws-iam`` (Used by AWS EKS IAM Role to Kubernetes Service Account Binding (IRSA) and EKS Pod Identity Authentication. Support for AWS IRSA is considered experimental in the secureCodeBox)
authType: access-secret-key
# Name to a k8s secret in the same namespace as this release with credentials to the s3 bucket. Only used when s3.authType is set to "access-secret-key"
# By default this assumes to have 'accesskey' and 'secretkey' as attributes
Expand All @@ -178,7 +178,7 @@ s3:
secretAttributeNames:
accesskey: accesskey
secretkey: secretkey
# s3.awsStsEndpoint -- STS Endpoint used in AWS IRSA Authentication. Change this to the sts endpoint of your aws region. Only used when s3.authType is set to "aws-irsa"
# s3.awsStsEndpoint -- STS Endpoint used in AWS IRSA Authentication. Change this to the sts endpoint of your aws region. Only used when s3.authType is set to "aws-iam". Usually not required, even in IRSA or Pod Identity setups as the region gets injected by AWS into the pod.
awsStsEndpoint: "https://sts.amazonaws.com"

# -- Go Template that generates the path used to store raw result file and findings.json file in the s3 bucket. Can be used to store the files in a subfolder of the s3 bucket
Expand Down
Loading