shellmakefilegnu-make

GNU Make variable values with special characters


I have an issue in a Makefile where I'm trying to read a value in from an AWS secret manager secret into a Make variable as follows:

$(eval SECRET_NAME := some/aws/secretname)
$(eval SECRET_FILE := .secret.json)
$(shell aws secretsmanager get-secret-value --region $(AWS_REGION) --secret-id $(SECRET_NAME) --query 'SecretString' --output text > $(SECRET_FILE))
$(eval MYSECRET := $(shell jq -r '.secret' $(SECRET_FILE)))

The secret might look like this:

{"username":"username","secret":"sUpEr$eCr3t@#2VaLu3)DontTellAny1"}

The problem is the 'secret' might contain any combination of characters, some of which are special to Make. I don't control the creation of these secrets, so 'pre-escaping' the special characters isn't possible when these secrets are created.

In the example as above, the value of $(MYSECRET) when used later in the Makefile, ends up being something like:

sUpEr3t@

I've tried various combinations of variable assignments like =, :=, ::= and can't find one that works correctly.

Am I just going to be forced to push the output of the aws secretsmanager get-secret-value through sed or similar to escape the values?

Are there other solutions to this issue?

update: sample makefile and values:

Makefile:

vars:
    $(eval SECRET_FILE := secretfile.json)
    $(eval USERNAME := $(shell jq -r '.username' $(SECRET_FILE)))
    $(eval PASSWORD = $(shell jq -r '.secret' $(SECRET_FILE)))
    @cat $(SECRET_FILE)
    @echo ""
    @jq -r '.secret' $(SECRET_FILE)
    @echo "user: $(USERNAME)"
    @echo "pass: $(PASSWORD)"

secretfile.json:

{"username":"myusername","secret":"sUpEr$eCr3t@2VaL#3)DontTellAny1"}

output:

$ make vars -f testfile.mk
{"username":"myusername","secret":"sUpEr$eCr3t@2VaL#3)DontTellAny1"}

sUpEr$eCr3t@2VaL#3)DontTellAny1
user: myusername
pass: sUpErCr3t@2VaL


Solution

  • If I change the example Makefile above to the following, parsing the variables globally before the target:

    SECRET_FILE := secretfile.json
    PASSWORD := $(shell jq -r '.secret' $(SECRET_FILE))
    USERNAME := $(shell jq -r '.username' $(SECRET_FILE))
    
    vars:
        @cat $(SECRET_FILE)
        @jq -r '.secret' $(SECRET_FILE)
        @echo 'user: $(value USERNAME)'
        @echo 'pass: $(value PASSWORD)'
    

    Then I get the expected output:

    $ make vars -f testfile.mk
    {"username":"myusername","secret":"sUpEr$eCr3t@2VaL#3)DontTellAny1"}
    sUpEr$eCr3t@2VaL#3)DontTellAny1
    user: myusername
    pass: sUpEr$eCr3t@2VaL#3)DontTellAny1
    

    Note that the argument to echo has to be enclosed in single quotes also to prevent the shell from attempting to parse and expand the value as well.