Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Source -> Destination for templates & secrets #171

Open
taylorsmithgg opened this issue Aug 19, 2020 · 6 comments
Open

Source -> Destination for templates & secrets #171

taylorsmithgg opened this issue Aug 19, 2020 · 6 comments
Labels
enhancement New feature or request

Comments

@taylorsmithgg
Copy link

Is your feature request related to a problem? Please describe.
Currently, I am forced to add cp /vault/secrets/file /destination to my entrypoint in order to use a templated config in most practical configuration scenarios that do not allow config location overrides.

Furthermore, local development environments do not provide the needed directory /vault/secrets without fostering it, so we have to maintain two sources of truth:
1.) The dev docker configuration
2.) The chart/manifest for kubernetes

However, in most cases, we want to keep the same structure as the source code in order to maintain a seamless dev -> production environment.

With the introduction of the new annotation for defining the path, this is now possible for non-existing paths , but not for replacements or even adding a file to an existing path.

This is currently possible using confd with a vault backend.

Confd also allows us to decide whether or not to keep the staged file in the event we need to compare the rendered template to a replaced file. This allows us to apply a default configuration that is used during development, but overwritten in kubernetes.

The major difference is that my project (git repo) can define the source and destination, as well as the templates.

Currently, the recommended approach is using annotations, based on the examples.

This vastly simplifies the integration of complex configuration files across multiple kubernetes environments.

For example:

# using dot env style configuration files (Javascript or PHP)
/vault/secrets/env -> /app/.env

# using yml configuration files (Java)
/vault/secrets/application.yml -> /app/config/application.yml

Describe the solution you'd like
The features of confd are currently more expressive and inline with regular development cycles.

I would like to see vault adopt some of these patterns:
1.) file replacement, with options for keeping original file
2.) ability to write to existing paths, source -> destination
3.) Better integration from git repo -> vault template

There is a limited example of using a postgres connection string in configmaps, but requires a lot of overhead in order to automate the process of converting git repo contents for templates -> configmap.

One of the biggest drawbacks for the current tutorials around these features are that they are extremely limited in scope.
It would be great to have an example that showed overriding a spring boot or nodejs hello world app with an overidden config using templates.

Describe alternatives you've considered
For the moment, I am using confd with vault as a backend.

Additional context
As mentioned before, moving long configurations into configmaps is possible, but still requires complex automation to copy from git repository -> configmap -> /vault/secrets -> /destination

PHP as obnoxious example config annotation

  vault.hashicorp.com/agent-inject-template-config: |
    <?php
    error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT);
    //ini_set('display_errors', 1);
    //ini_set('display_startup_errors', 1);
    /**
     * Application configuration
     */
    $conf['settings']['app.title'] = 'Scheduler';			// application title
    $conf['settings']['default.timezone'] = 'America/New_York';      // look up here http://php.net/manual/en/timezones.php
    $conf['settings']['allow.self.registration'] = 'true';         	// if users can register themselves
    $conf['settings']['admin.email'] = '[email protected]';         // email address of admin user
    $conf['settings']['admin.email.name'] = 'Administrator';	// name to be used in From: field when sending automatic emails
    $conf['settings']['default.page.size'] = '50';                  // number of records per page
    $conf['settings']['enable.email'] = 'true';                     // global configuration to enable if any emails will be sent
    $conf['settings']['default.language'] = 'en_us';                // find your language in the lang directory
    $conf['settings']['script.url'] = 'localhost:5000/Web';   	// public URL to the Web directory of this instance. this is the URL that appears when you are logging in. leave http: or https: off to auto-detect
    $conf['settings']['image.upload.directory'] = 'Web/uploads/images'; // full or relative path to where images will be stored
    $conf['settings']['image.upload.url'] = 'uploads/images';       // full or relative path to show uploaded images from
    $conf['settings']['cache.templates'] = 'true';                  // true recommended, caching template files helps web pages render faster
    $conf['settings']['use.local.js.libs'] = 'false';                // false recommended, delivers jQuery from Google CDN, uses less bandwidth
    $conf['settings']['registration.captcha.enabled'] = 'false';     // recommended. unless using recaptcha this requires php_gd2 enabled in php.ini
    $conf['settings']['registration.require.email.activation'] = 'false';		// requires enable.email = true
    $conf['settings']['registration.auto.subscribe.email'] = 'false';			// requires enable.email = true
    $conf['settings']['registration.notify.admin'] = 'false';		// whether the registration of a new user sends an email to the admin (ala phpScheduleIt 1.2)
    $conf['settings']['inactivity.timeout'] = '30';     			// minutes before the user is automatically logged out
    $conf['settings']['name.format'] = '{first} {last}';     		// display format when showing user names
    $conf['settings']['css.extension.file'] = ''; 			      	// full or relative url to an additional css file to include. this can be used to override the default style
    $conf['settings']['disable.password.reset'] = 'false'; 	      	// if the password reset functionality should be disabled
    $conf['settings']['home.url'] = ''; 	      					// the url to open when the logo is clicked
    $conf['settings']['logout.url'] = ''; 	      					// the url to be directed to after logging out
    $conf['settings']['default.homepage'] = '1'; 	      			// the default homepage to use when new users register (1 = Dashboard, 2 = Schedule, 3 = My Calendar, 4 = Resource Calendar)
    $conf['settings']['schedule']['use.per.user.colors'] = 'false'; 		// color reservations by user
    $conf['settings']['schedule']['show.inaccessible.resources'] = 'true';  // whether or not resources that are inaccessible to the user are visible
    $conf['settings']['schedule']['reservation.label'] = '{name}';    		// format for what to display on the reservation slot label.  Available properties are: {name}, {title}, {description}, {email}, {phone}, {organization}, {position}, {startdate}, {enddate} {resourcename} {participants} {invitees} {reservationAttributes}. Custom attributes can be added using att with the attribute id. For example {att1}
    $conf['settings']['schedule']['hide.blocked.periods'] = 'false';    	// if blocked periods should be hidden or shown
    $conf['settings']['schedule']['update.highlight.minutes'] = '0';    // if set, will show reservations as 'updated' for a certain amount of time
    /**
     * ical integration configuration
     */
    $conf['settings']['ics']['subscription.key'] = '';              // must be set to allow webcal subscriptions
    $conf['settings']['ics']['future.days'] = 30;
    $conf['settings']['ics']['past.days'] = 0;
    /**
     * Privacy configuration
     */
    $conf['settings']['privacy']['view.schedules'] = 'true';       			// if unauthenticated users can view schedules
    $conf['settings']['privacy']['view.reservations'] = 'false';    			// if unauthenticated users can view reservations
    $conf['settings']['privacy']['hide.user.details'] = 'false';    			// if personal user details should be displayed to non-administrators
    $conf['settings']['privacy']['hide.reservation.details'] = 'false';			// if reservation details should be displayed to non-administrators. options are true, false, current, future, past
    $conf['settings']['privacy']['allow.guest.reservations'] = 'false';			// if reservations can be made by users without a Booked account, if true this overrides schedule and resource visibility
    /**
     * Reservation specific configuration
     */
    $conf['settings']['reservation']['start.time.constraint'] = 'future';		// when reservations can be created or edited. options are future, current, none
    $conf['settings']['reservation']['updates.require.approval'] = 'false';		// if updates to previously approved reservations require approval again
    $conf['settings']['reservation']['prevent.participation'] = 'false';		// if participation and invitation options should be removed
    $conf['settings']['reservation']['prevent.recurrence'] = 'false';			// if recurring reservations are disabled for non-administrators
    $conf['settings']['reservation']['enable.reminders'] = 'false';				// if reminders are enabled. this requires email to be enabled and the reminder job to be configured
    $conf['settings']['reservation']['allow.guest.participation'] = 'false';
    $conf['settings']['reservation']['allow.wait.list'] = 'false';
    $conf['settings']['reservation']['checkin.minutes.prior'] = '5';
    $conf['settings']['reservation']['default.start.reminder'] = '';			// the default start reservation reminder. format is ## interval. for example, 10 minutes, 2 hours, 6 days.
    $conf['settings']['reservation']['default.end.reminder'] = '';				// the default end reservation reminder. format is ## interval. for example, 10 minutes, 2 hours, 6 days.
    $conf['settings']['reservation']['title.required'] = 'false';
    $conf['settings']['reservation']['description.required'] = 'false';
    /**
     * Email notification configuration
     */
    $conf['settings']['reservation.notify']['resource.admin.add'] = 'false';
    $conf['settings']['reservation.notify']['resource.admin.update'] = 'false';
    $conf['settings']['reservation.notify']['resource.admin.delete'] = 'false';
    $conf['settings']['reservation.notify']['resource.admin.approval'] = 'false';
    $conf['settings']['reservation.notify']['application.admin.add'] = 'false';
    $conf['settings']['reservation.notify']['application.admin.update'] = 'false';
    $conf['settings']['reservation.notify']['application.admin.delete'] = 'false';
    $conf['settings']['reservation.notify']['application.admin.approval'] = 'false';
    $conf['settings']['reservation.notify']['group.admin.add'] = 'false';
    $conf['settings']['reservation.notify']['group.admin.update'] = 'false';
    $conf['settings']['reservation.notify']['group.admin.delete'] = 'false';
    $conf['settings']['reservation.notify']['group.admin.approval'] = 'false';
    /**
     * File upload configuration
     */
    $conf['settings']['uploads']['enable.reservation.attachments'] = 'false'; 	// if reservation attachments can be uploaded
    $conf['settings']['uploads']['reservation.attachment.path'] = 'uploads/reservation'; 	// full or relative (to the root of your installation) filesystem path to store reservation attachments
    $conf['settings']['uploads']['reservation.attachment.extensions'] = 'txt,jpg,gif,png,doc,docx,pdf,xls,xlsx,ppt,pptx,csv'; 	// comma separated list of file extensions that users are allowed to attach. leave empty to allow all extensions
    /**
     * Database configuration
     */
    $conf['settings']['database']['type'] = 'mysql';
    $conf['settings']['database']['name'] = 'database';
    {{ with secret "kv/booked/settings/database" }}
    $conf['settings']['database']['hostspec'] = '{{ .Data.data.hostspec }}';        // ip, dns or named pipe
    $conf['settings']['database']['user'] = '{{ .Data.data.user }}';        // database user with permission to the booked database
    $conf['settings']['database']['password'] = '{{ .Data.data.password }}';
    {{ end }}
    /**
     * Mail server configuration
     */
    $conf['settings']['phpmailer']['mailer'] = 'smtp';              // options are 'mail', 'smtp' or 'sendmail'
    $conf['settings']['phpmailer']['sendmail.path'] = '/usr/sbin/sendmail';
    $conf['settings']['phpmailer']['smtp.port'] = '465';
    $conf['settings']['phpmailer']['smtp.secure'] = 'ssl';            // options are '', 'ssl' or 'tls'
    $conf['settings']['phpmailer']['smtp.auth'] = 'true';           // options are 'true' or 'false'
    $conf['settings']['phpmailer']['smtp.debug'] = 'false';
    {{ with secret "kv/booked/settings/phpmailer" }} 
    $conf['settings']['phpmailer']['smtp.host'] = '{{ .Data.data.host }}';               // 'smtp.company.com'
    $conf['settings']['phpmailer']['smtp.username'] = '{{ .Data.data.username }}';
    $conf['settings']['phpmailer']['smtp.password'] = '{{ .Data.data.password }}';
    {{ end }}
    /**
     * Plugin configuration.  For more on plugins, see readme_installation.html
     */
    $conf['settings']['plugins']['Authentication'] = '';
    $conf['settings']['plugins']['Authorization'] = '';
    $conf['settings']['plugins']['Permission'] = '';
    $conf['settings']['plugins']['PostRegistration'] = '';
    $conf['settings']['plugins']['PreReservation'] = '';
    $conf['settings']['plugins']['PostReservation'] = '';
    /**
     * Installation settings
     */
    $conf['settings']['install.password'] = '';
    /**
     * Pages
     */
    $conf['settings']['pages']['enable.configuration'] = 'true';
    /**
     * API
     */
    $conf['settings']['api']['enabled'] = 'false';
    $conf['settings']['api']['allow.self.registration'] = 'false';
    /**
     * ReCaptcha
     */
    $conf['settings']['recaptcha']['enabled'] = 'false';
    $conf['settings']['recaptcha']['public.key'] = '';
    $conf['settings']['recaptcha']['private.key'] = '';
    /**
     * Email
     */
    $conf['settings']['email']['default.from.address'] = '';
    $conf['settings']['email']['default.from.name'] = '';
    /**
     * Reports
     */
    $conf['settings']['reports']['allow.all.users'] = 'false';
    /**
     * Account Password Rules
     */
    $conf['settings']['password']['minimum.letters'] = '6';
    $conf['settings']['password']['minimum.numbers'] = '0';
    $conf['settings']['password']['upper.and.lower'] = 'false';
    /**
     * Label display settings
     */
    $conf['settings']['reservation.labels']['ics.summary'] = '{title}';
    $conf['settings']['reservation.labels']['ics.my.summary'] = '{title}';
    $conf['settings']['reservation.labels']['rss.description'] = '<div><span>Start</span> {startdate}</div><div><span>End</span> {enddate}</div><div><span>Organizer</span> {name}</div><div><span>Description</span> {description}</div>';
    $conf['settings']['reservation.labels']['my.calendar'] = '{resourcename} {title}';
    $conf['settings']['reservation.labels']['resource.calendar'] = '{name}';
    $conf['settings']['reservation.labels']['reservation.popup'] = ''; // Format for what to display in reservation popups. Possible values: {name} {dates} {title} {resources} {participants} {accessories} {description} {attributes} {pending} {duration}. Custom attributes can be added using att with the attribute id. For example {att1}
    /**
     * Security header settings
     */
    $conf['settings']['security']['security.headers'] = 'false'; // Enable the following options
    $conf['settings']['security']['security.strict-transport'] = 'true';
    $conf['settings']['security']['security.x-frame'] = 'deny';
    $conf['settings']['security']['security.x-xss'] = '1; mode=block';
    $conf['settings']['security']['security.x-content-type'] = 'nosniff';
    $conf['settings']['security']['security.content-security-policy'] = ""; // Requires careful tuning (know what your doing)
    /**
     * Google Analytics settings
     */
    $conf['settings']['google.analytics']['tracking.id'] = ''; // if set, Google Analytics tracking code will be added to every page in Booked
    $conf['settings']['authentication']['allow.facebook.login'] = 'true';
    $conf['settings']['authentication']['allow.google.login'] = 'true';
    $conf['settings']['authentication']['required.email.domains'] = '';
    $conf['settings']['authentication']['hide.booked.login.prompt'] = 'false';
    $conf['settings']['authentication']['captcha.on.login'] = 'false';
    /**
     * Credits
     */
    $conf['settings']['credits']['enabled'] = 'false';
    $conf['settings']['credits']['allow.purchase'] = 'false';
    /**
     * Slack integration
     */
    $conf['settings']['slack']['token'] = '';
    /**
     * Tablet view
     */
    $conf['settings']['tablet.view']['allow.guest.reservations'] = 'false';
    $conf['settings']['tablet.view']['auto.suggest.emails'] = 'false';
@taylorsmithgg taylorsmithgg added the enhancement New feature or request label Aug 19, 2020
@jasonodonnell
Copy link
Contributor

Hi @taylorsmithgg, this should be possible with this feature: #158.

This will be in the next release of Vault K8s.

@taylorsmithgg
Copy link
Author

I do not believe that PR fully addresses this use case, but possibly one key piece of it.

If you could provide a fully-formed example, I would be happy to confirm!

@wernerb
Copy link

wernerb commented Aug 21, 2020

@jasonodonnell sorry for the direct mention. I have been hit with the issue that we need the same filename for a secret in multiple directories. Is it possible to cut a release?

@jasonodonnell
Copy link
Contributor

Our next release is planned Monday, August 24th @wernerb!

@jasonodonnell
Copy link
Contributor

@taylorsmithgg, you could try this (using the newest release 0.5.0):

vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/agent-inject-status: "update"
vault.hashicorp.com/agent-inject-secret-kv-secret: "secret/hashiconf"
vault.hashicorp.com/agent-inject-template-kv-secret: |
    {{ with secret "secret/hashiconf" }}{{ .Data | toJSONPretty }}{{ end }}
vault.hashicorp.com/secret-volume-path-kv-secret: "/etc/mysecret"
vault.hashicorp.com/agent-inject-file-kv-secret: "secret.json" 
vault.hashicorp.com/role: "app"

@taylorsmithgg
Copy link
Author

Looks good!
I'll give it a try and get back to you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants