Skip to content

Commit 1c9f06a

Browse files
committed
feat(build): #252 aws secrets from env
- Allow in makes.nix to specify aws secrets from env vars - No secret values are dumped to the nix-store, of course. Just env-var names (which are not secret)
1 parent a18934c commit 1c9f06a

File tree

10 files changed

+243
-21
lines changed

10 files changed

+243
-21
lines changed

README.md

+114-17
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ in just a few steps, in any technology.
3030
- [Makes.nix format](#makesnix-format)
3131
- [Caching](#caching)
3232
- [cache](#cache)
33+
- [Secrets](#secrets)
34+
- [secrets](#secrets)
35+
- [aws](#aws)
36+
- [fromEnv](#fromenv)
3337
- [Formatters](#formatters)
3438
- [formatBash](#formatbash)
3539
- [formatMarkdown](#formatmarkdown)
@@ -445,6 +449,103 @@ Example `makes.nix`:
445449
}
446450
```
447451

452+
## Secrets
453+
454+
Managing secrets is critical for application security.
455+
456+
The following functions are secure
457+
and allow you to re-use secrets
458+
across different [Makes][MAKES] components.
459+
460+
### secrets
461+
462+
#### aws
463+
464+
Secrets for authenticating into [Amazon Web Services (AWS)][AWS].
465+
466+
##### fromEnv
467+
468+
Load [AWS][AWS] secrets from [Environment Variables][ENV_VAR].
469+
470+
Attributes:
471+
472+
- self (`attrsOf awsFromEnvType`): Optional.
473+
Defaults to `{ }`.
474+
475+
Custom Types:
476+
477+
- awsFromEnvType (`submodule`):
478+
479+
- accessKeyId (`str`): Optional.
480+
Name of the [environment variable][ENV_VAR]
481+
that stores the value of the [AWS][AWS] Access Key Id.
482+
Defaults to `"AWS_ACCESS_KEY_ID"`.
483+
484+
- defaultRegion (`str`): Optional.
485+
Name of the [environment variable][ENV_VAR]
486+
that stores the value of the [AWS][AWS] Default Region.
487+
Defaults to `"us-east-1"`.
488+
489+
- secretAccessKey (`str`): Optional.
490+
Name of the [environment variable][ENV_VAR]
491+
that stores the value of the [AWS][AWS] Secret Access Key.
492+
Defaults to `"AWS_SECRET_ACCESS_KEY"`.
493+
494+
- sessionToken (`str`): Optional.
495+
Name of the [environment variable][ENV_VAR]
496+
that stores the value of the [AWS][AWS] Session Token.
497+
Defaults to `"AWS_SESSION_TOKEN"`.
498+
499+
Always available outputs:
500+
501+
- `/secrets/aws/fromEnv/__default__`:
502+
- accessKeyId: "AWS_ACCESS_KEY_ID";
503+
- defaultRegion: "us-east-1";
504+
- secretAccessKey: "AWS_SECRET_ACCESS_KEY";
505+
- sessionToken: "AWS_SESSION_TOKEN";
506+
507+
Example `makes.nix`:
508+
509+
```nix
510+
{ outputs
511+
, ...
512+
}:
513+
{
514+
secrets = {
515+
aws = {
516+
fromEnv = {
517+
makesDev = {
518+
accessKeyId = "MAKES_DEV_AWS_ACCESS_KEY_ID";
519+
secretAccessKey = "MAKES_DEV_AWS_SECRET_ACCESS_KEY";
520+
};
521+
makesProd = {
522+
accessKeyId = "MAKES_PROD_AWS_ACCESS_KEY_ID";
523+
secretAccessKey = "MAKES_PROD_AWS_SECRET_ACCESS_KEY";
524+
};
525+
};
526+
};
527+
};
528+
lintTerraform = {
529+
modules = {
530+
moduleDev = {
531+
authentication = [
532+
outputs."/secrets/aws/fromEnv/makesDev"
533+
];
534+
src = "/my/module1";
535+
version = "0.12";
536+
};
537+
moduleProd = {
538+
authentication = [
539+
outputs."/secrets/aws/fromEnv/makesProd"
540+
];
541+
src = "/my/module2";
542+
version = "0.12";
543+
};
544+
};
545+
};
546+
}
547+
```
548+
448549
## Formatters
449550

450551
Formatters help your code be consistent, beautiful and more maintainable.
@@ -803,19 +904,14 @@ Attributes:
803904
Custom Types:
804905

805906
- moduleType (`submodule`):
907+
- authentication (`listOf package`): Optional.
908+
[Makes Secrets][MAKES_SECRETS] to use (if required by your module).
909+
Defaults to `[ ]`.
806910
- src (`str`):
807911
Path to the [Terraform][TERRAFORM] module.
808912
- version (`str`):
809913
[Terraform][TERRAFORM] version your module is built with.
810914

811-
Required environment variables:
812-
813-
- If your [Terraform][TERRAFORM] module uses the AWS provider:
814-
- `AWS_ACCESS_KEY_ID`
815-
- `AWS_DEFAULT_REGION`
816-
- `AWS_SECRET_ACCESS_KEY`
817-
- `AWS_SESSION_TOKEN`: Required only if the AWS credentials are temporary.
818-
819915
Example `makes.nix`:
820916

821917
```nix
@@ -835,15 +931,7 @@ Example `makes.nix`:
835931
}
836932
```
837933

838-
Example invocation:
839-
840-
```bash
841-
$ AWS_ACCESS_KEY_ID=123 \
842-
AWS_DEFAULT_REGION=us-east-1 \
843-
AWS_SECRET_ACCESS_KEY=123 \
844-
AWS_SESSION_TOKEN=123 \
845-
m . /lintTerraform
846-
```
934+
Example invocation: `$ m . /lintTerraform`
847935

848936
### lintWithLizard
849937

@@ -1579,6 +1667,9 @@ $ m . /example
15791667
- [APACHE_MAVEN]: https://maven.apache.org/
15801668
[Apache Maven][APACHE_MAVEN]
15811669
1670+
- [AWS]: https://aws.amazon.com/
1671+
[Amazon Web Services (AWS)][AWS]
1672+
15821673
- [BASH]: https://www.gnu.org/software/bash/
15831674
[Bash][BASH]
15841675
@@ -1609,6 +1700,9 @@ $ m . /example
16091700
- [DOCTOC]: https://github.com/thlorenz/doctoc
16101701
[DocToc][DOCTOC]
16111702
1703+
- [ENV_VAR]: https://en.wikipedia.org/wiki/Environment_variable
1704+
[Environment Variable][ENV_VAR]
1705+
16121706
- [FLUID_ATTACKS]: https://fluidattacks.com
16131707
[Fluid Attacks][FLUID_ATTACKS]
16141708
@@ -1663,6 +1757,9 @@ $ m . /example
16631757
- [MAKES_RELEASES]: https://github.com/fluidattacks/makes/releases
16641758
[Makes Releases][MAKES_RELEASES]
16651759
1760+
- [MAKES_SECRETS]: #secrets
1761+
[Makes Secrets][MAKES_SECRETS]
1762+
16661763
- [MARKDOWN_LINT]: https://github.com/markdownlint/markdownlint
16671764
[Markdown lint tool][MARKDOWN_LINT]
16681765

src/args/default.nix

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ let
3131
makeScript = import ./make-script/default.nix args;
3232
makeScriptParallel = import ./make-script-parallel/default.nix args;
3333
makeSearchPaths = import ./make-search-paths/default.nix args;
34+
makeSecretAwsFromEnv = import ./make-secret-aws-from-env/default.nix args;
3435
makeTerraformEnvironment = import ./make-terraform-environment/default.nix args;
3536
inherit makesVersion;
3637
makeTemplate = import ./make-template/default.nix args;

src/args/lint-terraform/default.nix

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
, makeTerraformEnvironment
44
, ...
55
}:
6-
{ config
6+
{ authentication
7+
, config
78
, name
89
, version
910
, src
@@ -24,6 +25,6 @@ makeScript {
2425
(makeTerraformEnvironment {
2526
inherit version;
2627
})
27-
];
28+
] ++ authentication;
2829
};
2930
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{ makeTemplate
2+
, ...
3+
}:
4+
{ accessKeyId
5+
, defaultRegion
6+
, name
7+
, secretAccessKey
8+
, sessionToken
9+
}:
10+
makeTemplate {
11+
replace = {
12+
__argAccessKeyId__ = accessKeyId;
13+
__argDefaultRegion__ = defaultRegion;
14+
__argSecretAcessKey__ = secretAccessKey;
15+
__argSessionToken__ = sessionToken;
16+
};
17+
name = "make-secret-aws-from-env-for-${name}";
18+
template = ./template.sh;
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# shellcheck shell=bash
2+
3+
function main {
4+
local access_key_id_name='__argAccessKeyId__'
5+
local default_region_name='__argDefaultRegion__'
6+
local secret_access_key_name='__argSecretAcessKey__'
7+
local session_token_name='__argSessionToken__'
8+
9+
require_env_var "${access_key_id_name}" \
10+
&& require_env_var "${default_region_name}" \
11+
&& require_env_var "${secret_access_key_name}" \
12+
&& export AWS_ACCESS_KEY_ID="${!access_key_id_name}" \
13+
&& export AWS_DEFAULT_REGION="${!default_region_name}" \
14+
&& export AWS_ACCESS_KEY_ID="${!secret_access_key_name}" \
15+
&& export AWS_SESSION_TOKEN="${!session_token_name:-}"
16+
}
17+
18+
main "${@}"

src/args/shell-commands/makes-setup.sh

+8
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,11 @@ function copy {
3030
cp --no-target-directory --recursive "${@}" \
3131
&& chmod --recursive +w "${@: -1}"
3232
}
33+
34+
function require_env_var {
35+
local var_name="${1}"
36+
37+
if test -z "${!var_name:-}"; then
38+
critical Env var is required but is empty or not present: "${var_name}"
39+
fi
40+
}

src/cli/main/__main__.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,10 @@ def _help_and_exit(
250250
_log()
251251
_log("[OUTPUT] can be:")
252252
for attr in attrs:
253-
if attr not in {"__all__"}:
253+
if attr not in {
254+
"__all__",
255+
"/secrets/aws/fromEnv/__default__",
256+
}:
254257
_log(f" {attr}")
255258
if exc is not None:
256259
_log()

src/evaluator/modules/default.nix

+1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ args:
66
(import ./inputs.nix)
77
(import ./outputs/default.nix args)
88
(import ./required-makes-version.nix args)
9+
(import ./secrets.nix args)
910
];
1011
}

src/evaluator/modules/outputs/builtins/lint-terraform/default.nix

+6-1
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@
99
, ...
1010
}:
1111
let
12-
makeOutput = name: { src, version }: {
12+
makeOutput = name: { authentication, src, version }: {
1313
name = "/lintTerraform/${name}";
1414
value = lintTerraform {
15+
inherit authentication;
1516
config = builtins.toFile "tflint.hcl" config.lintTerraform.config;
1617
inherit name;
1718
src = path src;
@@ -37,6 +38,10 @@ in
3738
default = { };
3839
type = lib.types.attrsOf (lib.types.submodule (_: {
3940
options = {
41+
authentication = lib.mkOption {
42+
default = [ ];
43+
type = lib.types.listOf lib.types.package;
44+
};
4045
src = lib.mkOption {
4146
type = lib.types.str;
4247
};

src/evaluator/modules/secrets.nix

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
{ __toModuleOutputs__
2+
, makeSecretAwsFromEnv
3+
, ...
4+
}:
5+
{ config
6+
, lib
7+
, ...
8+
}:
9+
let
10+
awsFromEnvType = lib.types.submodule (_: {
11+
options = {
12+
accessKeyId = lib.mkOption {
13+
default = "AWS_ACCESS_KEY_ID";
14+
type = lib.types.str;
15+
};
16+
defaultRegion = lib.mkOption {
17+
default = "us-east-1";
18+
type = lib.types.str;
19+
};
20+
secretAccessKey = lib.mkOption {
21+
default = "AWS_SECRET_ACCESS_KEY";
22+
type = lib.types.str;
23+
};
24+
sessionToken = lib.mkOption {
25+
default = "AWS_SESSION_TOKEN";
26+
type = lib.types.str;
27+
};
28+
};
29+
});
30+
makeAwsFromEnvOutput = name:
31+
{ accessKeyId
32+
, defaultRegion
33+
, secretAccessKey
34+
, sessionToken
35+
}: {
36+
name = "/secrets/aws/fromEnv/${name}";
37+
value = makeSecretAwsFromEnv {
38+
inherit accessKeyId;
39+
inherit defaultRegion;
40+
inherit name;
41+
inherit secretAccessKey;
42+
inherit sessionToken;
43+
};
44+
};
45+
in
46+
{
47+
options = {
48+
secrets = {
49+
aws = {
50+
fromEnv = lib.mkOption {
51+
default = { };
52+
type = lib.types.attrsOf awsFromEnvType;
53+
};
54+
};
55+
};
56+
};
57+
config = {
58+
outputs =
59+
(__toModuleOutputs__ makeAwsFromEnvOutput config.secrets.aws.fromEnv) //
60+
(__toModuleOutputs__ makeAwsFromEnvOutput {
61+
__default__ = {
62+
accessKeyId = "AWS_ACCESS_KEY_ID";
63+
defaultRegion = "us-east-1";
64+
secretAccessKey = "AWS_SECRET_ACCESS_KEY";
65+
sessionToken = "AWS_SESSION_TOKEN";
66+
};
67+
});
68+
};
69+
}

0 commit comments

Comments
 (0)