Environment variables interpolation does not work when using before/after hooks #860

Closed
opened 2024-04-28 16:24:48 +00:00 by valfur03 · 7 comments

What I'm trying to do and why

I want to backup a database while performing some actions using the before_backup hook.

Steps to reproduce

  1. Setup the database connection in mariadb_databases. Here is my configuration:
    # /etc/borgmatic.d/database.yaml
    <<: !include
        - hooks/before.yaml
    
    constants:
        mariadb_name: name
        mariadb_host: host
        mariadb_user: user
        mariadb_pass: ${MARIADB_PASSWORD}
    
    mariadb_databases:
        !include sources/mariadb-database.yaml
    
    repositories:
        !include repositories/all.yaml
    
    # /etc/borgmatic.d/hooks/before.yaml
    before_backup: []
    
    # sources/mariadb-database.yaml
    - name: "{mariadb_name}"
      hostname: "{mariadb_host}"
      username: "{mariadb_user}"
      password: "{mariadb_pass}"
    
  2. Run a create action (borgmatic --stats --list --verbosity 1)

Actual behavior

Borgmatic exits with error code 1 and prints this:

/etc/borgmatic.d/database.yaml: An error occurred                            
local: Error running actions for repository                                            
mariadb-dump: Got error: 1045: "Access denied for user 'user'@'192.168.16.6' (using password: YES)" when trying to connect
Command 'mariadb-dump --add-drop-database --host host --protocol tcp --user user --databases name --result-file /root/.borgmatic/mariadb_databases/database/name returned non-zero exit status 2.                                            

Expected behavior

It should perform the backup successfully.

Other notes / implementation ideas

I tried hardcoding the password constant:

mariadb_pass: mydbpass

This way it works fine. That is why my guess is that environment variable iterpolation stops working when before/after hooks are set, even empty.

I had no idea what to try to be sure about that.

Note that environment variables exist and are set if I try to echo them in before_backup hook.

borgmatic version

1.8.10

borgmatic installation method

Docker container

Borg version

1.2.8

Python version

3.12.3

Database version (if applicable)

mariadb v11.2

Operating system and version

Alpine Linux 3.19.1

### What I'm trying to do and why I want to backup a database while performing some actions using the `before_backup` hook. ### Steps to reproduce 1. Setup the database connection in `mariadb_databases`. Here is my configuration: ```yaml # /etc/borgmatic.d/database.yaml <<: !include - hooks/before.yaml constants: mariadb_name: name mariadb_host: host mariadb_user: user mariadb_pass: ${MARIADB_PASSWORD} mariadb_databases: !include sources/mariadb-database.yaml repositories: !include repositories/all.yaml # /etc/borgmatic.d/hooks/before.yaml before_backup: [] # sources/mariadb-database.yaml - name: "{mariadb_name}" hostname: "{mariadb_host}" username: "{mariadb_user}" password: "{mariadb_pass}" ``` 2. Run a create action (`borgmatic --stats --list --verbosity 1`) ### Actual behavior Borgmatic exits with error code 1 and prints this: ``` /etc/borgmatic.d/database.yaml: An error occurred local: Error running actions for repository mariadb-dump: Got error: 1045: "Access denied for user 'user'@'192.168.16.6' (using password: YES)" when trying to connect Command 'mariadb-dump --add-drop-database --host host --protocol tcp --user user --databases name --result-file /root/.borgmatic/mariadb_databases/database/name returned non-zero exit status 2. ``` ### Expected behavior It should perform the backup successfully. ### Other notes / implementation ideas I tried hardcoding the password constant: ```yaml mariadb_pass: mydbpass ``` This way it works fine. That is why my guess is that environment variable iterpolation stops working when before/after hooks are set, even empty. I had no idea what to try to be sure about that. Note that environment variables exist and are set if I try to `echo` them in `before_backup` hook. ### borgmatic version 1.8.10 ### borgmatic installation method Docker container ### Borg version 1.2.8 ### Python version 3.12.3 ### Database version (if applicable) mariadb v11.2 ### Operating system and version Alpine Linux 3.19.1
Owner

Thanks for filing this! Unfortunately I haven't been able to reproduce it thus far on my system. I've tried a very similar configuration: A constant consuming an environment variable, and then using that constant in included database configuration. It all works as expected here.

So a couple of ideas on how to proceed:

  • Have you double checked that the password as set from the environment variable is correct?
  • Is it possible that the password contains a special character that's tripping up your shell (or borgmatic), a special character doesn't cause problems when hard-coded in the constant? If you think that might be a problem, can you try a simpler password temporarily to see if that solves it?
  • Maybe try simpler variants of the configuration, like using the environment variable directly without an intermediate constant.. or using the environment variable and constant but cutting out includes.

Let me know what you find out!

Thanks for filing this! Unfortunately I haven't been able to reproduce it thus far on my system. I've tried a very similar configuration: A constant consuming an environment variable, and then using that constant in included database configuration. It all works as expected here. So a couple of ideas on how to proceed: * Have you double checked that the password as set from the environment variable is correct? * Is it possible that the password contains a special character that's tripping up your shell (or borgmatic), a special character doesn't cause problems when hard-coded in the constant? If you think that might be a problem, can you try a simpler password temporarily to see if that solves it? * Maybe try simpler variants of the configuration, like using the environment variable directly without an intermediate constant.. or using the environment variable and constant but cutting out includes. Let me know what you find out!
Author

Thanks for your answer. Unfortunately, none of the solutions worked on my part.

I have provided you a sample repository for you to try to reproduce this error: https://github.com/valfur03/borgmatic-env-issue-860

Some additional notes, I have tested on both amd64 and armv8 architectures.

Thanks again for your help!

Thanks for your answer. Unfortunately, none of the solutions worked on my part. I have provided you a sample repository for you to try to reproduce this error: https://github.com/valfur03/borgmatic-env-issue-860 Some additional notes, I have tested on both amd64 and armv8 architectures. Thanks again for your help!
Owner

Thank you so much for setting up a sample repro! I have indeed managed to reproduce the issue with it, and it looks like what's going on is that borgmatic's constants code is very intentionally shell escaping all constant values, in theory to prevent shell injection attacks. Unfortunately that also prevents environment variable substitution within constant values, which is exactly what you're trying to do here. I'll have to think about what can be done about this.

Thank you so much for setting up a sample repro! I have indeed managed to reproduce the issue with it, and it looks like what's going on is that borgmatic's constants code is very intentionally shell escaping all constant values, in theory to prevent shell injection attacks. Unfortunately that also prevents environment variable substitution within constant values, which is exactly what you're trying to do here. I'll have to think about what can be done about this.
Owner

Update! I have a fix in hand.. I just need to write tests for it. It turned out that there was already code to selectively apply the shell escaping logic, and it wasn't supposed to apply to constants used in database passwords, but it was being applied anyway. I'll let you know once this fix is pushed.

Update! I have a fix in hand.. I just need to write tests for it. It turned out that there was already code to selectively apply the shell escaping logic, and it wasn't _supposed_ to apply to constants used in database passwords, but it was being applied anyway. I'll let you know once this fix is pushed.
Owner

Okay, the fix is pushed and will be part of the next release. Thanks again!

Okay, the fix is pushed and will be part of the next release. Thanks again!
witten added the
bug
label 2024-04-30 16:38:46 +00:00
Author

I have tested locally and everything works fine!

Thank you so much for your help!

I have tested locally and everything works fine! Thank you so much for your help!
Owner

Awesome, glad to hear it!

Awesome, glad to hear it!
Sign in to join this conversation.
No Milestone
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: borgmatic-collective/borgmatic#860
No description provided.