Skip to content

Commit

Permalink
feat(build, secrets): include plain secret values in giterminism scope (
Browse files Browse the repository at this point in the history
#6495)

Signed-off-by: Yaroslav Pershin <62902094+iapershin@users.noreply.github.com>
Co-authored-by: Aleksei Igrychev <alexey.igrychev@flant.com>
  • Loading branch information
iapershin and alexey-igrychev authored Dec 18, 2024
1 parent ebe3e4b commit 1508e30
Show file tree
Hide file tree
Showing 13 changed files with 131 additions and 2 deletions.
7 changes: 6 additions & 1 deletion docs/_data/werf_giterminism_yaml.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ directives:
ru: Правила использования значений секретов
directives:
- name: allowEnvVariables
value: "[ string || /REGEXP/, ... ]"
value: "[ string, ... ]"
description:
en: Allow the use of specific environment variables as secrets
ru: Разрешить использование определённых переменных окружения в качестве секретов
Expand All @@ -62,6 +62,11 @@ directives:
description:
en: Allow the use of specific paths to files as secrets
ru: Разрешить использование определённых путей к файлам в качестве секретов
- name: allowValueIds
value: "[ string, ... ]"
description:
en: Allow the use of specific identifiers of arbitrary secret values
ru: Разрешить использование определённых идентификаторов произвольных значений секретов
- name: stapel
description:
en: The rules for the stapel image
Expand Down
16 changes: 16 additions & 0 deletions docs/pages_en/usage/build/images.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ In the example above, werf will use the Dockerfile at `docs/Dockerfile` to build

#### Using build secrets

> **NOTE:** To use secrets in builds, you need to enable them explicitly in the giterminism settings. Learn more ([here]({{ "/usage/project_configuration/giterminism.html#using-build-secrets" | true_relative_url }}))

A build secret is any sensitive information, such as a password or API token, required during the build process of your application.

Build arguments and environment variables are not suitable for passing secrets to the build process, as they are retained in the final image.
Expand All @@ -153,6 +155,20 @@ secrets:
value: plainSecretValue
```

```yaml
# werf-giterminism.yaml
giterminismConfigVersion: 1
config:
secrets:
allowEnvVariables:
- "AWS_ACCESS_KEY_ID"
allowFiles:
- "~/.aws/credentials"
allowValueIds:
- plainSecret
```

To access a secret during the build, use the `--mount=type=secret` flag in the Dockerfile's `RUN` instructions.

When a secret is mounted, it is available as a file by default. The default mount path for the secret file inside the build container is `/run/secrets/<id>`. If an `id` is not specified for a secret in `werf.yaml`, the default value is assigned automatically:
Expand Down
24 changes: 24 additions & 0 deletions docs/pages_en/usage/build/stapel/instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -342,12 +342,18 @@ In the example above the current commit hash will be inserted into the `echo ...

## Using build secrets

> **NOTE:** To use secrets in builds, you need to enable them explicitly in the giterminism settings. Learn more ([here]({{ "/usage/project_configuration/giterminism.html#using-build-secrets" | true_relative_url }}))

A build secret is any confidential information, such as a password or API token, used during the build process of your application.

Build arguments and environment variables are not suitable for passing secrets during a build, as they may be retained in the final image.
You can use secrets during the build process by defining them in `werf.yaml`.

```yaml
# werf.yaml
project: example
configVersion: 1
---
image: stapel-shell
from: ubuntu:22.04
secrets:
Expand All @@ -359,6 +365,20 @@ secrets:
value: plainSecretValue
```

```yaml
# werf-giterminism.yaml
giterminismConfigVersion: 1
config:
secrets:
allowEnvVariables:
- "AWS_ACCESS_KEY_ID"
allowFiles:
- "~/.aws/credentials"
allowValueIds:
- plainSecret
```

When using a secret in Stapel instructions, the secret is mounted to a file. The path for the secret file inside the build container is `/run/secrets/<id>`. If an `id` is not specified for a secret in `werf.yaml`, the default value is assigned automatically:

- For `env`, the `id` defaults to the name of the environment variable.
Expand All @@ -367,6 +387,10 @@ When using a secret in Stapel instructions, the secret is mounted to a file. The
> For `value` — the `id` field is mandatory.

```yaml
# werf.yaml
project: example
configVersion: 1
---
image: stapel-shell
from: ubuntu:22.04
secrets:
Expand Down
12 changes: 12 additions & 0 deletions docs/pages_en/usage/project_configuration/giterminism.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,18 @@ The use of the [fromPath]({{"usage/build/stapel/mounts.html" | true_relative_url

The `fromPath` directive can be activated using [werf-giterminism.yaml]({{"reference/werf_giterminism_yaml.html" | true_relative_url }}), but we strongly recommend that you carefully consider the possible implications of this.

#### Using build secrets

The use of secrets complicates the sharing and reproducibility of configuration in CI jobs and among developers.

To manage secrets and ensure their consistent use, you can configure the [werf-giterminism.yaml]({{ "reference/werf_giterminism_yaml.html" | true_relative_url }}) file with the following:

- `allowEnvVariables` — allows the use of specific environment variables.
- `allowFiles` — grants access to secrets stored in specified files.
- `allowValueIds` — enables the use of arbitrary secret values identified by IDs.

We strongly recommend carefully considering the potential implications and avoiding the use of secrets unless absolutely necessary.

### Deploying

#### The --use-custom-tag option
Expand Down
15 changes: 15 additions & 0 deletions docs/pages_ru/usage/build/images.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ dockerfile: Dockerfile

#### Использование сборочных секретов

> **ЗАМЕЧАНИЕ:** Чтобы использовать секреты в сборках, их нужно явно разрешить в настройках гитерминизма. Подробнее ([здесь]({{ "/usage/project_configuration/giterminism.html#использование-сборочных-секретов" | true_relative_url }}))

Секрет сборки — это любая конфиденциальная информация, например пароль или токен API, используемая в процессе сборки вашего приложения.

Аргументы сборки и переменные окружения не подходят для передачи секретов в сборку, поскольку они сохраняются в конечном образе.
Expand All @@ -152,6 +154,19 @@ secrets:
- id: plainSecret
value: plainSecretValue
```
```yaml
# werf-giterminism.yaml
giterminismConfigVersion: 1
config:
secrets:
allowEnvVariables:
- "AWS_ACCESS_KEY_ID"
allowFiles:
- "~/.aws/credentials"
allowValueIds:
- plainSecret
```

Чтобы использовать секрет в сборке и сделать его доступным для инструкции `RUN`, используйте флаг `--mount=type=secret` в Dockerfile.

Expand Down
20 changes: 20 additions & 0 deletions docs/pages_ru/usage/build/stapel/instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -364,12 +364,18 @@ shell:

## Использование сборочных секретов

> **ЗАМЕЧАНИЕ:** Чтобы использовать секреты в сборках, их нужно явно разрешить в настройках гитерминизма. Подробнее ([здесь]({{ "/usage/project_configuration/giterminism.html#использование-сборочных-секретов" | true_relative_url }}))

Секрет сборки — это любая конфиденциальная информация, например пароль или токен API, используемая в процессе сборки вашего приложения.

Аргументы сборки и переменные окружения не подходят для передачи секретов в сборку, поскольку они сохраняются в конечном образе.
Вы можете использовать секреты при сборке, описав их в `werf.yaml`.

```yaml
# werf.yaml
project: example
configVersion: 1
---
image: stapel-shell
from: ubuntu:22.04
secrets:
Expand All @@ -381,6 +387,20 @@ secrets:
value: plainSecretValue
```

```yaml
# werf-giterminism.yaml
giterminismConfigVersion: 1
config:
secrets:
allowEnvVariables:
- "AWS_ACCESS_KEY_ID"
allowFiles:
- "~/.aws/credentials"
allowValueIds:
- plainSecret
```

При использовании секрета в Stapel инструкциях, секрет монтируется в файл по умолчанию. Путь к файлу секрета по умолчанию внутри контейнера сборки — `/run/secrets/<id>`. Если `id` секрета явно не указан в `werf.yaml`, то в качестве `id` будет использовано значение по умолчанию:

- Для `env` — имя переменной окружения.
Expand Down
12 changes: 12 additions & 0 deletions docs/pages_ru/usage/project_configuration/giterminism.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,18 @@ werf не позволяет работать с незакоммиченным

Для активации директивы `fromPath` необходимо использовать [werf-giterminism.yaml]({{ "reference/werf_giterminism_yaml.html" | true_relative_url }}), но мы рекомендуем еще раз подумать о возможных последствиях.

#### Использование сборочных секретов

Использование секретов усложняет совместное использование и воспроизводимость конфигурации в заданиях CI и среди разработчиков.

Чтобы управлять секретами и обеспечить их согласованное использование, в файле [werf-giterminism.yaml]({{ "reference/werf_giterminism_yaml.html" | true_relative_url }}) можно настроить:

- `allowEnvVariables` — разрешение использования определённых переменных окружения.
- `allowFiles` — доступ к секретам из указанных файлов.
- `allowValueIds` — использование произвольных значений секретов по идентификаторам.

Мы рекомендуем еще раз подумать о возможных последствиях и не использовать секреты без реальной необходимости.

### Развёртывание

#### Опция --use-custom-tag
Expand Down
2 changes: 1 addition & 1 deletion pkg/config/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func (s *SecretFromSrc) InspectByGiterminism(giterminismManager giterminism_mana
}

func (s *SecretFromPlainValue) InspectByGiterminism(giterminismManager giterminism_manager.Interface) error {
return nil
return giterminismManager.Inspector().InspectConfigSecretValueAccepted(s.Id)
}

func GetValidatedSecrets(rawSecrets []*rawSecret, giterminismManager giterminism_manager.Interface, doc *doc) ([]Secret, error) {
Expand Down
9 changes: 9 additions & 0 deletions pkg/giterminism_manager/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ func (c Config) IsConfigSecretSrcAccepted(path string) bool {
return c.Config.Secrets.IsAllowSecretsFileAccepted(path)
}

func (c Config) IsConfigSecretValueAccepted(path string) bool {
return c.Config.Secrets.IsValueIdAccepted(path)
}

type cli struct {
AllowCustomTags bool `json:"allowCustomTags"`
}
Expand Down Expand Up @@ -223,6 +227,7 @@ func pathMatcher(patterns []string) path_matcher.PathMatcher {
type secrets struct {
AllowEnvVariables []string `json:"allowEnvVariables"`
AllowFiles []string `json:"allowFiles"`
AllowValueIds []string `json:"allowValueIds"`
}

func (s *secrets) IsEnvNameAccepted(name string) bool {
Expand All @@ -233,6 +238,10 @@ func (s *secrets) IsAllowSecretsFileAccepted(path string) bool {
return isAbsPathMatched(s.AllowFiles, path)
}

func (s *secrets) IsValueIdAccepted(name string) bool {
return slices.Contains(s.AllowValueIds, name)
}

func isAbsPathMatched(patterns []string, p string) bool {
absPath := make([]string, 0, len(patterns))
for _, p := range patterns {
Expand Down
12 changes: 12 additions & 0 deletions pkg/giterminism_manager/inspector/config_secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,15 @@ func (i Inspector) InspectConfigSecretSrcAccepted(secret string) error {

return NewExternalDependencyFoundError(fmt.Sprintf(secretsErrMsg, secret))
}

func (i Inspector) InspectConfigSecretValueAccepted(secret string) error {
if i.sharedOptions.LooseGiterminism() {
return nil
}

if i.giterminismConfig.IsConfigSecretValueAccepted(secret) {
return nil
}

return NewExternalDependencyFoundError(fmt.Sprintf(secretsErrMsg, secret))
}
1 change: 1 addition & 0 deletions pkg/giterminism_manager/inspector/inspector.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type giterminismConfig interface {
IsConfigDockerfileContextAddFileAccepted(relPath string) bool
IsConfigSecretEnvAccepted(name string) bool
IsConfigSecretSrcAccepted(path string) bool
IsConfigSecretValueAccepted(name string) bool
}

type fileReader interface {
Expand Down
1 change: 1 addition & 0 deletions pkg/giterminism_manager/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,5 @@ type Inspector interface {
InspectBuildContextFiles(ctx context.Context, matcher path_matcher.PathMatcher) error
InspectConfigSecretEnvAccepted(secret string) error
InspectConfigSecretSrcAccepted(secret string) error
InspectConfigSecretValueAccepted(secret string) error
}
2 changes: 2 additions & 0 deletions test/e2e/build/_fixtures/simple/state1/werf-giterminism.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ config:
allowFiles:
- "./file"
- "~/secret_file_in_home"
allowValueIds:
- plainSecret

0 comments on commit 1508e30

Please sign in to comment.