mirror of
https://github.com/saltstack/salt.git
synced 2025-04-16 09:40:20 +00:00
nacl updates
This commit is contained in:
parent
fa8d672f9a
commit
2b79ba2f32
3 changed files with 725 additions and 166 deletions
|
@ -5,3 +5,4 @@ yappi>=0.8.2
|
|||
--allow-unverified python-neutronclient>2.3.6
|
||||
python-gnupg
|
||||
cherrypy>=3.2.2
|
||||
libnacl
|
||||
|
|
|
@ -11,112 +11,157 @@ regardless if they are encrypted or not.
|
|||
When generating keys and encrypting passwords use --local when using salt-call for extra
|
||||
security. Also consider using just the salt runner nacl when encrypting pillar passwords.
|
||||
|
||||
:configuration: The following configuration defaults can be
|
||||
define (pillar or config files) Avoid storing private keys in pillars! Ensure master does not have `pillar_opts=True`:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# cat /etc/salt/master.d/nacl.conf
|
||||
nacl.config:
|
||||
# NOTE: `key` and `key_file` have been renamed to `sk`, `sk_file`
|
||||
# also `box_type` default changed from secretbox to sealedbox.
|
||||
box_type: sealedbox (default)
|
||||
sk_file: /etc/salt/pki/master/nacl (default)
|
||||
pk_file: /etc/salt/pki/master/nacl.pub (default)
|
||||
sk: None
|
||||
pk: None
|
||||
|
||||
Usage can override the config defaults:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-call nacl.enc sk_file=/etc/salt/pki/master/nacl pk_file=/etc/salt/pki/master/nacl.pub
|
||||
|
||||
|
||||
The nacl lib uses 32byte keys, these keys are base64 encoded to make your life more simple.
|
||||
To generate your `key` or `keyfile` you can use:
|
||||
To generate your `sk_file` and `pk_file` use:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-call --local nacl.keygen keyfile=/root/.nacl
|
||||
salt-call --local nacl.keygen sk_file=/etc/salt/pki/master/nacl
|
||||
# or if you want to work without files.
|
||||
salt-call --local nacl.keygen
|
||||
local:
|
||||
----------
|
||||
pk:
|
||||
/kfGX7PbWeu099702PBbKWLpG/9p06IQRswkdWHCDk0=
|
||||
sk:
|
||||
SVWut5SqNpuPeNzb1b9y6b2eXg2PLIog43GBzp48Sow=
|
||||
|
||||
Now with your key, you can encrypt some data:
|
||||
Now with your keypair, you can encrypt data:
|
||||
|
||||
You have two option, `sealedbox` or `secretbox`.
|
||||
|
||||
SecretBox is data encrypted using private key `pk`. Sealedbox is encrypted using public key `pk`.
|
||||
|
||||
Recommend using Sealedbox because the one way encryption permits developers to encrypt data for source control but not decrypt.
|
||||
Sealedbox only has one key that is for both encryption and decryption.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-call --local nacl.enc mypass keyfile=/root/.nacl
|
||||
DRB7Q6/X5gGSRCTpZyxS6hXO5LnlJIIJ4ivbmUlbWj0llUA+uaVyvou3vJ4=
|
||||
salt-call --local nacl.enc asecretpass pk=/kfGX7PbWeu099702PBbKWLpG/9p06IQRswkdWHCDk0=
|
||||
tqXzeIJnTAM9Xf0mdLcpEdklMbfBGPj2oTKmlgrm3S1DTVVHNnh9h8mU1GKllGq/+cYsk6m5WhGdk58=
|
||||
|
||||
To decrypt the data:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-call --local nacl.dec data='DRB7Q6/X5gGSRCTpZyxS6hXO5LnlJIIJ4ivbmUlbWj0llUA+uaVyvou3vJ4=' keyfile=/root/.nacl
|
||||
mypass
|
||||
salt-call --local nacl.dec data='tqXzeIJnTAM9Xf0mdLcpEdklMbfBGPj2oTKmlgrm3S1DTVVHNnh9h8mU1GKllGq/+cYsk6m5WhGdk58=' \
|
||||
sk='SVWut5SqNpuPeNzb1b9y6b2eXg2PLIog43GBzp48Sow='
|
||||
|
||||
The following optional configurations can be defined in the
|
||||
minion or master config. Avoid storing the config in pillars!
|
||||
When the keys are defined in the master config you can use them from the nacl runner
|
||||
without extra parameters:
|
||||
|
||||
.. code-block:: yaml
|
||||
.. code-block:: python
|
||||
|
||||
cat /etc/salt/master.d/nacl.conf
|
||||
# cat /etc/salt/master.d/nacl.conf
|
||||
nacl.config:
|
||||
key: 'cKEzd4kXsbeCE7/nLTIqXwnUiD1ulg4NoeeYcCFpd9k='
|
||||
keyfile: /root/.nacl
|
||||
|
||||
When the key is defined in the master config you can use it from the nacl runner:
|
||||
sk_file: /etc/salt/pki/master/nacl
|
||||
pk: 'cTIqXwnUiD1ulg4kXsbeCE7/NoeKEzd4nLeYcCFpd9k='
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-run nacl.enc 'myotherpass'
|
||||
salt-run nacl.enc 'asecretpass'
|
||||
salt-run nacl.dec 'tqXzeIJnTAM9Xf0mdLcpEdklMbfBGPj2oTKmlgrm3S1DTVVHNnh9h8mU1GKllGq/+cYsk6m5WhGdk58='
|
||||
|
||||
Now you can create a pillar with protected data like:
|
||||
.. code-block:: yam
|
||||
# a salt developers minion could have pillar data that includes a nacl public key
|
||||
nacl.config:
|
||||
pk: '/kfGX7PbWeu099702PBbKWLpG/9p06IQRswkdWHCDk0='
|
||||
|
||||
The developer can then use a less secure system to encrypt data.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-call --local nacl.enc apassword
|
||||
|
||||
|
||||
Pillar files can include protected data that the salt master decrypts:
|
||||
|
||||
.. code-block:: jinja
|
||||
|
||||
pillarexample:
|
||||
user: root
|
||||
password: {{ salt.nacl.dec('DRB7Q6/X5gGSRCTpZyxS6hXO5LnlJIIJ4ivbmUlbWj0llUA+uaVyvou3vJ4=') }}
|
||||
password1: {{salt.nacl.dec('DRB7Q6/X5gGSRCTpZyxS6hlbWj0llUA+uaVyvou3vJ4=')|json}}
|
||||
cert_key: {{salt.nacl.dec_file('/srv/salt/certs/example.com/key.nacl')|json}}
|
||||
cert_key2: {{salt.nacl.dec_file('salt:///certs/example.com/key.nacl')|json}}
|
||||
|
||||
Or do something interesting with grains like:
|
||||
|
||||
.. code-block:: jinja
|
||||
|
||||
salt-call nacl.enc minionname:dbrole
|
||||
AL24Z2C5OlkReer3DuQTFdrNLchLuz3NGIhGjZkLtKRYry/b/CksWM8O9yskLwH2AGVLoEXI5jAa
|
||||
|
||||
salt minionname grains.setval role 'AL24Z2C5OlkReer3DuQTFdrNLchLuz3NGIhGjZkLtKRYry/b/CksWM8O9yskLwH2AGVLoEXI5jAa'
|
||||
|
||||
{%- set r = grains.get('role') %}
|
||||
{%- set role = None %}
|
||||
{%- if r and 'nacl.dec' in salt %}
|
||||
{%- set r = salt['nacl.dec'](r,keyfile='/root/.nacl').split(':') %}
|
||||
{%- if opts['id'] == r[0] %}
|
||||
{%- set role = r[1] %}
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
base:
|
||||
{%- if role %}
|
||||
'{{ opts['id'] }}':
|
||||
- {{ role }}
|
||||
{%- endif %}
|
||||
|
||||
Multi-line text items like certificates require a bit of extra work. You have to strip the new lines
|
||||
and replace them with '/n' characters. Certificates specifically require some leading white space when
|
||||
calling nacl.enc so that the '--' in the first line (commonly -----BEGIN CERTIFICATE-----) doesn't get
|
||||
interpreted as an argument to nacl.enc. For instance if you have a certificate file that lives in cert.crt:
|
||||
Larger files like certificates can be encrypted with:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cert=$(cat cert.crt |awk '{printf "%s\\n",$0} END {print ""}'); salt-run nacl.enc " $cert"
|
||||
salt-call nacl.enc_file /tmp/cert.crt out=/tmp/cert.nacl
|
||||
# or more advanced
|
||||
cert=$(cat /tmp/cert.crt)
|
||||
salt-call --out=newline_values_only nacl.enc_pub data="$cert" > /tmp/cert.nacl
|
||||
|
||||
Pillar data should look the same, even though the secret will be quite long. However, when calling
|
||||
multiline encrypted secrets from pillar in a state, use the following format to avoid issues with /n
|
||||
creating extra whitespace at the beginning of each line in the cert file:
|
||||
In Pillars rended with jinja be sure to include `|json` so line breaks are encoded:
|
||||
|
||||
.. code-block:: jinja
|
||||
|
||||
secret.txt:
|
||||
file.managed:
|
||||
- template: jinja
|
||||
- user: user
|
||||
- group: group
|
||||
- mode: 700
|
||||
- contents: "{{- salt['pillar.get']('secret') }}"
|
||||
cert: "{{salt.nacl.dec('S2uogToXkgENz9...085KYt')|json}}"
|
||||
|
||||
In States rendered with jinja it is also good pratice to include `|json`:
|
||||
|
||||
.. code-block:: jinja
|
||||
|
||||
{{sls}} private key:
|
||||
file.managed:
|
||||
- name: /etc/ssl/private/cert.key
|
||||
- mode: 700
|
||||
- contents: "{{pillar['pillarexample']['cert_key']|json}}"
|
||||
|
||||
|
||||
Optional small program to encrypt data without needing salt modules.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
#!/bin/python3
|
||||
import sys, base64, libnacl.sealed
|
||||
pk = base64.b64decode('YOURPUBKEY')
|
||||
b = libnacl.sealed.SealedBox(pk)
|
||||
data = sys.stdin.buffer.read()
|
||||
print(base64.b64encode(b.encrypt(data)).decode())
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
echo 'apassword' | nacl_enc.py
|
||||
|
||||
The '{{-' will tell jinja to strip the whitespace from the beginning of each of the new lines.
|
||||
'''
|
||||
|
||||
from __future__ import absolute_import
|
||||
import base64
|
||||
import os
|
||||
import salt.utils.files
|
||||
import salt.utils
|
||||
import salt.syspaths
|
||||
|
||||
|
||||
REQ_ERROR = None
|
||||
try:
|
||||
import libnacl.secret
|
||||
import libnacl.sealed
|
||||
except (ImportError, OSError) as e:
|
||||
REQ_ERROR = 'libnacl import error, perhaps missing python libnacl package'
|
||||
REQ_ERROR = 'libnacl import error, perhaps missing python libnacl package or should update.'
|
||||
|
||||
__virtualname__ = 'nacl'
|
||||
|
||||
|
@ -130,91 +175,284 @@ def _get_config(**kwargs):
|
|||
Return configuration
|
||||
'''
|
||||
config = {
|
||||
'key': None,
|
||||
'keyfile': None,
|
||||
'box_type': 'sealedbox',
|
||||
'sk': None,
|
||||
'sk_file': '/etc/salt/pki/master/nacl',
|
||||
'pk': None,
|
||||
'pk_file': '/etc/salt/pki/master/nacl.pub',
|
||||
}
|
||||
config_key = '{0}.config'.format(__virtualname__)
|
||||
try:
|
||||
config.update(__salt__['config.get'](config_key, {}))
|
||||
for k in set(config) & set(kwargs):
|
||||
except (NameError, KeyError) as e:
|
||||
# likly using salt-run so fallback to __opts__
|
||||
config.update(__opts__.get(config_key, {}))
|
||||
# pylint: disable=C0201
|
||||
for k in set(config.keys()) & set(kwargs.keys()):
|
||||
config[k] = kwargs[k]
|
||||
return config
|
||||
|
||||
|
||||
def _get_key(rstrip_newline=True, **kwargs):
|
||||
def _get_sk(**kwargs):
|
||||
'''
|
||||
Return key
|
||||
Return sk
|
||||
'''
|
||||
config = _get_config(**kwargs)
|
||||
key = config['key']
|
||||
keyfile = config['keyfile']
|
||||
if not key and keyfile:
|
||||
if not os.path.isfile(keyfile):
|
||||
raise Exception('file not found: {0}'.format(keyfile))
|
||||
with salt.utils.files.fopen(keyfile, 'rb') as keyf:
|
||||
key = keyf.read()
|
||||
key = config['sk']
|
||||
sk_file = config['sk_file']
|
||||
if not key and sk_file:
|
||||
with salt.utils.fopen(sk_file, 'rb') as keyf:
|
||||
key = str(keyf.read()).rstrip('\n')
|
||||
if key is None:
|
||||
raise Exception('no key found')
|
||||
key = str(key)
|
||||
if rstrip_newline:
|
||||
key = key.rstrip('\n')
|
||||
return key
|
||||
raise Exception('no key or sk_file found')
|
||||
return base64.b64decode(key)
|
||||
|
||||
|
||||
def keygen(keyfile=None):
|
||||
def _get_pk(**kwargs):
|
||||
'''
|
||||
Use libnacl to generate a private key
|
||||
Return pk
|
||||
'''
|
||||
config = _get_config(**kwargs)
|
||||
pubkey = config['pk']
|
||||
pk_file = config['pk_file']
|
||||
if not pubkey and pk_file:
|
||||
with salt.utils.fopen(pk_file, 'rb') as keyf:
|
||||
pubkey = str(keyf.read()).rstrip('\n')
|
||||
if pubkey is None:
|
||||
raise Exception('no pubkey or pk_file found')
|
||||
pubkey = str(pubkey)
|
||||
return base64.b64decode(pubkey)
|
||||
|
||||
|
||||
def keygen(sk_file=None, pk_file=None):
|
||||
'''
|
||||
Use libnacl to generate a keypair.
|
||||
|
||||
If no `sk_file` is defined return a keypair.
|
||||
|
||||
If only the `sk_file` is defined `pk_file` will use the same name with a postfix `.pub`.
|
||||
|
||||
When the `sk_file` is already existing, but `pk_file` is not. The `pk_file` will be generated
|
||||
using the `sk_file`.
|
||||
|
||||
CLI Examples:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-call nacl.keygen
|
||||
salt-call nacl.keygen sk_file=/etc/salt/pki/master/nacl
|
||||
salt-call nacl.keygen sk_file=/etc/salt/pki/master/nacl pk_file=/etc/salt/pki/master/nacl.pub
|
||||
salt-call --local nacl.keygen
|
||||
salt-call --local nacl.keygen keyfile=/root/.nacl
|
||||
salt-call --local --out=newline_values_only nacl.keygen > /root/.nacl
|
||||
'''
|
||||
b = libnacl.secret.SecretBox()
|
||||
key = b.sk
|
||||
key = base64.b64encode(key)
|
||||
if keyfile:
|
||||
if os.path.isfile(keyfile):
|
||||
raise Exception('file already found: {0}'.format(keyfile))
|
||||
with salt.utils.files.fopen(keyfile, 'w') as keyf:
|
||||
keyf.write(key)
|
||||
return 'saved: {0}'.format(keyfile)
|
||||
return key
|
||||
if sk_file is None:
|
||||
kp = libnacl.public.SecretKey()
|
||||
return {'sk': base64.b64encode(kp.sk), 'pk': base64.b64encode(kp.pk)}
|
||||
|
||||
if pk_file is None:
|
||||
pk_file = '{0}.pub'.format(sk_file)
|
||||
|
||||
if sk_file and pk_file is None:
|
||||
if not os.path.isfile(sk_file):
|
||||
kp = libnacl.public.SecretKey()
|
||||
with salt.utils.fopen(sk_file, 'w') as keyf:
|
||||
keyf.write(base64.b64encode(kp.sk))
|
||||
if not salt.utils.is_windows():
|
||||
os.chmod(sk_file, 1536) # 0600
|
||||
return 'saved sk_file: {0}'.format(sk_file)
|
||||
else:
|
||||
raise Exception('sk_file:{0} already exist.'.format(sk_file))
|
||||
|
||||
if sk_file is None and pk_file:
|
||||
raise Exception('sk_file: Must be set inorder to generate a public key.')
|
||||
|
||||
if os.path.isfile(sk_file) and os.path.isfile(pk_file):
|
||||
raise Exception('sk_file:{0} and pk_file:{1} already exist.'.format(sk_file, pk_file))
|
||||
|
||||
if os.path.isfile(sk_file) and not os.path.isfile(pk_file):
|
||||
# generate pk using the sk
|
||||
with salt.utils.fopen(sk_file, 'rb') as keyf:
|
||||
sk = str(keyf.read()).rstrip('\n')
|
||||
sk = base64.b64decode(sk)
|
||||
kp = libnacl.public.SecretKey(sk)
|
||||
with salt.utils.fopen(pk_file, 'w') as keyf:
|
||||
keyf.write(base64.b64encode(kp.pk))
|
||||
return 'saved pk_file: {0}'.format(pk_file)
|
||||
|
||||
kp = libnacl.public.SecretKey()
|
||||
with salt.utils.fopen(sk_file, 'w') as keyf:
|
||||
keyf.write(base64.b64encode(kp.sk))
|
||||
if not salt.utils.is_windows():
|
||||
os.chmod(sk_file, 1536) # 0600
|
||||
with salt.utils.fopen(pk_file, 'w') as keyf:
|
||||
keyf.write(base64.b64encode(kp.pk))
|
||||
return 'saved sk_file:{0} pk_file: {1}'.format(sk_file, pk_file)
|
||||
|
||||
|
||||
def enc(data, **kwargs):
|
||||
'''
|
||||
Takes a key generated from `nacl.keygen` and encrypt some data.
|
||||
Alias to `{box_type}_encrypt`
|
||||
|
||||
box_type: secretbox, sealedbox(default)
|
||||
'''
|
||||
box_type = _get_config(**kwargs)['box_type']
|
||||
if box_type == 'sealedbox':
|
||||
return sealedbox_encrypt(data, **kwargs)
|
||||
if box_type == 'secretbox':
|
||||
return secretbox_encrypt(data, **kwargs)
|
||||
return sealedbox_encrypt(data, **kwargs)
|
||||
|
||||
|
||||
def enc_file(name, out=None, **kwargs):
|
||||
'''
|
||||
This is a helper function to encrypt a file and return its contents.
|
||||
|
||||
You can provide an optional output file using `out`
|
||||
|
||||
`name` can be a local file or when not using `salt-run` can be a url like `salt://`, `https://` etc.
|
||||
|
||||
CLI Examples:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-call --local nacl.enc datatoenc
|
||||
salt-call --local nacl.enc datatoenc keyfile=/root/.nacl
|
||||
salt-call --local nacl.enc datatoenc key='cKEzd4kXsbeCE7/nLTIqXwnUiD1ulg4NoeeYcCFpd9k='
|
||||
salt-run nacl.enc_file name=/tmp/id_rsa
|
||||
salt-call nacl.enc_file name=salt://crt/mycert out=/tmp/cert
|
||||
salt-run nacl.enc_file name=/tmp/id_rsa box_type=secretbox \
|
||||
sk_file=/etc/salt/pki/master/nacl.pub
|
||||
'''
|
||||
key = _get_key(**kwargs)
|
||||
sk = base64.b64decode(key)
|
||||
b = libnacl.secret.SecretBox(sk)
|
||||
return base64.b64encode(b.encrypt(data))
|
||||
try:
|
||||
data = __salt__['cp.get_file_str'](name)
|
||||
except Exception as e:
|
||||
# likly using salt-run so fallback to local filesystem
|
||||
with salt.utils.fopen(name, 'rb') as f:
|
||||
data = f.read()
|
||||
d = enc(data, **kwargs)
|
||||
if out:
|
||||
if os.path.isfile(out):
|
||||
raise Exception('file:{0} already exist.'.format(out))
|
||||
with salt.utils.fopen(out, 'wb') as f:
|
||||
f.write(d)
|
||||
return 'Wrote: {0}'.format(out)
|
||||
return d
|
||||
|
||||
|
||||
def dec(data, **kwargs):
|
||||
'''
|
||||
Takes a key generated from `nacl.keygen` and decrypt some data.
|
||||
Alias to `{box_type}_decrypt`
|
||||
|
||||
box_type: secretbox, sealedbox(default)
|
||||
'''
|
||||
box_type = _get_config(**kwargs)['box_type']
|
||||
if box_type == 'sealedbox':
|
||||
return sealedbox_decrypt(data, **kwargs)
|
||||
if box_type == 'secretbox':
|
||||
return secretbox_decrypt(data, **kwargs)
|
||||
return sealedbox_decrypt(data, **kwargs)
|
||||
|
||||
|
||||
def dec_file(name, out=None, **kwargs):
|
||||
'''
|
||||
This is a helper function to decrypt a file and return its contents.
|
||||
|
||||
You can provide an optional output file using `out`
|
||||
|
||||
`name` can be a local file or when not using `salt-run` can be a url like `salt://`, `https://` etc.
|
||||
|
||||
CLI Examples:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-call --local nacl.dec pEXHQM6cuaF7A=
|
||||
salt-call --local nacl.dec data='pEXHQM6cuaF7A=' keyfile=/root/.nacl
|
||||
salt-call --local nacl.dec data='pEXHQM6cuaF7A=' key='cKEzd4kXsbeCE7/nLTIqXwnUiD1ulg4NoeeYcCFpd9k='
|
||||
salt-run nacl.dec_file name=/tmp/id_rsa.nacl
|
||||
salt-call nacl.dec_file name=salt://crt/mycert.nacl out=/tmp/id_rsa
|
||||
salt-run nacl.dec_file name=/tmp/id_rsa.nacl box_type=secretbox \
|
||||
sk_file=/etc/salt/pki/master/nacl.pub
|
||||
'''
|
||||
key = _get_key(**kwargs)
|
||||
sk = base64.b64decode(key)
|
||||
b = libnacl.secret.SecretBox(key=sk)
|
||||
try:
|
||||
data = __salt__['cp.get_file_str'](name)
|
||||
except Exception as e:
|
||||
# likly using salt-run so fallback to local filesystem
|
||||
with salt.utils.fopen(name, 'rb') as f:
|
||||
data = f.read()
|
||||
d = dec(data, **kwargs)
|
||||
if out:
|
||||
if os.path.isfile(out):
|
||||
raise Exception('file:{0} already exist.'.format(out))
|
||||
with salt.utils.fopen(out, 'wb') as f:
|
||||
f.write(d)
|
||||
return 'Wrote: {0}'.format(out)
|
||||
return d
|
||||
|
||||
|
||||
def sealedbox_encrypt(data, **kwargs):
|
||||
'''
|
||||
Encrypt data using a public key generated from `nacl.keygen`.
|
||||
The encryptd data can be decrypted using `nacl.sealedbox_decrypt` only with the secret key.
|
||||
|
||||
CLI Examples:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-run nacl.sealedbox_encrypt datatoenc
|
||||
salt-call --local nacl.sealedbox_encrypt datatoenc pk_file=/etc/salt/pki/master/nacl.pub
|
||||
salt-call --local nacl.sealedbox_encrypt datatoenc pk='vrwQF7cNiNAVQVAiS3bvcbJUnF0cN6fU9YTZD9mBfzQ='
|
||||
'''
|
||||
pk = _get_pk(**kwargs)
|
||||
b = libnacl.sealed.SealedBox(pk)
|
||||
return base64.b64encode(b.encrypt(data))
|
||||
|
||||
|
||||
def sealedbox_decrypt(data, **kwargs):
|
||||
'''
|
||||
Decrypt data using a secret key that was encrypted using a public key with `nacl.sealedbox_encrypt`.
|
||||
|
||||
CLI Examples:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-call nacl.sealedbox_decrypt pEXHQM6cuaF7A=
|
||||
salt-call --local nacl.sealedbox_decrypt data='pEXHQM6cuaF7A=' sk_file=/etc/salt/pki/master/nacl
|
||||
salt-call --local nacl.sealedbox_decrypt data='pEXHQM6cuaF7A=' sk='YmFkcGFzcwo='
|
||||
'''
|
||||
if data is None:
|
||||
return None
|
||||
sk = _get_sk(**kwargs)
|
||||
keypair = libnacl.public.SecretKey(sk)
|
||||
b = libnacl.sealed.SealedBox(keypair)
|
||||
return b.decrypt(base64.b64decode(data))
|
||||
|
||||
|
||||
def secretbox_encrypt(data, **kwargs):
|
||||
'''
|
||||
Encrypt data using a secret key generated from `nacl.keygen`.
|
||||
The same secret key can be used to decrypt the data using `nacl.secretbox_decrypt`.
|
||||
|
||||
CLI Examples:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-run nacl.secretbox_encrypt datatoenc
|
||||
salt-call --local nacl.secretbox_encrypt datatoenc sk_file=/etc/salt/pki/master/nacl
|
||||
salt-call --local nacl.secretbox_encrypt datatoenc sk='YmFkcGFzcwo='
|
||||
'''
|
||||
sk = _get_sk(**kwargs)
|
||||
b = libnacl.secret.SecretBox(sk)
|
||||
return base64.b64encode(b.encrypt(data))
|
||||
|
||||
|
||||
def secretbox_decrypt(data, **kwargs):
|
||||
'''
|
||||
Decrypt data that was encrypted using `nacl.secretbox_encrypt` using the secret key
|
||||
that was generated from `nacl.keygen`.
|
||||
|
||||
CLI Examples:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-call nacl.secretbox_decrypt pEXHQM6cuaF7A=
|
||||
salt-call --local nacl.secretbox_decrypt data='pEXHQM6cuaF7A=' sk_file=/etc/salt/pki/master/nacl
|
||||
salt-call --local nacl.secretbox_decrypt data='pEXHQM6cuaF7A=' sk='YmFkcGFzcwo='
|
||||
'''
|
||||
if data is None:
|
||||
return None
|
||||
key = _get_sk(**kwargs)
|
||||
b = libnacl.secret.SecretBox(key=key)
|
||||
return b.decrypt(base64.b64decode(data))
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
This runner helps create encrypted passwords that can be included in pillars.
|
||||
This module helps include encrypted passwords in pillars, grains and salt state files.
|
||||
|
||||
:depends: libnacl, https://github.com/saltstack/libnacl
|
||||
|
||||
|
@ -8,35 +8,160 @@ This is often useful if you wish to store your pillars in source control or
|
|||
share your pillar data with others that you trust. I don't advise making your pillars public
|
||||
regardless if they are encrypted or not.
|
||||
|
||||
The following configurations can be defined in the master config
|
||||
so your users can create encrypted passwords using the runner nacl:
|
||||
When generating keys and encrypting passwords use --local when using salt-call for extra
|
||||
security. Also consider using just the salt runner nacl when encrypting pillar passwords.
|
||||
|
||||
.. code-block:: bash
|
||||
:configuration: The following configuration defaults can be
|
||||
define (pillar or config files) Avoid storing private keys in pillars! Ensure master does not have `pillar_opts=True`:
|
||||
|
||||
cat /etc/salt/master.d/nacl.conf
|
||||
.. code-block:: python
|
||||
|
||||
# cat /etc/salt/master.d/nacl.conf
|
||||
nacl.config:
|
||||
key: 'cKEzd4kXsbeCE7/nLTIqXwnUiD1ulg4NoeeYcCFpd9k='
|
||||
keyfile: /root/.nacl
|
||||
# NOTE: `key` and `key_file` have been renamed to `sk`, `sk_file`
|
||||
# also `box_type` default changed from secretbox to sealedbox.
|
||||
box_type: sealedbox (default)
|
||||
sk_file: /etc/salt/pki/master/nacl (default)
|
||||
pk_file: /etc/salt/pki/master/nacl.pub (default)
|
||||
sk: None
|
||||
pk: None
|
||||
|
||||
Now with the config in the master you can use the runner nacl like:
|
||||
Usage can override the config defaults:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-run nacl.enc 'data'
|
||||
salt-call nacl.enc sk_file=/etc/salt/pki/master/nacl pk_file=/etc/salt/pki/master/nacl.pub
|
||||
|
||||
|
||||
The nacl lib uses 32byte keys, these keys are base64 encoded to make your life more simple.
|
||||
To generate your `sk_file` and `pk_file` use:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-call --local nacl.keygen sk_file=/etc/salt/pki/master/nacl
|
||||
# or if you want to work without files.
|
||||
salt-call --local nacl.keygen
|
||||
local:
|
||||
----------
|
||||
pk:
|
||||
/kfGX7PbWeu099702PBbKWLpG/9p06IQRswkdWHCDk0=
|
||||
sk:
|
||||
SVWut5SqNpuPeNzb1b9y6b2eXg2PLIog43GBzp48Sow=
|
||||
|
||||
Now with your keypair, you can encrypt data:
|
||||
|
||||
You have two option, `sealedbox` or `secretbox`.
|
||||
|
||||
SecretBox is data encrypted using private key `pk`. Sealedbox is encrypted using public key `pk`.
|
||||
|
||||
Recommend using Sealedbox because the one way encryption permits developers to encrypt data for source control but not decrypt.
|
||||
Sealedbox only has one key that is for both encryption and decryption.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-call --local nacl.enc asecretpass pk=/kfGX7PbWeu099702PBbKWLpG/9p06IQRswkdWHCDk0=
|
||||
tqXzeIJnTAM9Xf0mdLcpEdklMbfBGPj2oTKmlgrm3S1DTVVHNnh9h8mU1GKllGq/+cYsk6m5WhGdk58=
|
||||
|
||||
To decrypt the data:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-call --local nacl.dec data='tqXzeIJnTAM9Xf0mdLcpEdklMbfBGPj2oTKmlgrm3S1DTVVHNnh9h8mU1GKllGq/+cYsk6m5WhGdk58=' \
|
||||
sk='SVWut5SqNpuPeNzb1b9y6b2eXg2PLIog43GBzp48Sow='
|
||||
|
||||
When the keys are defined in the master config you can use them from the nacl runner
|
||||
without extra parameters:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# cat /etc/salt/master.d/nacl.conf
|
||||
nacl.config:
|
||||
sk_file: /etc/salt/pki/master/nacl
|
||||
pk: 'cTIqXwnUiD1ulg4kXsbeCE7/NoeKEzd4nLeYcCFpd9k='
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-run nacl.enc 'asecretpass'
|
||||
salt-run nacl.dec 'tqXzeIJnTAM9Xf0mdLcpEdklMbfBGPj2oTKmlgrm3S1DTVVHNnh9h8mU1GKllGq/+cYsk6m5WhGdk58='
|
||||
|
||||
.. code-block:: yam
|
||||
# a salt developers minion could have pillar data that includes a nacl public key
|
||||
nacl.config:
|
||||
pk: '/kfGX7PbWeu099702PBbKWLpG/9p06IQRswkdWHCDk0='
|
||||
|
||||
The developer can then use a less secure system to encrypt data.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-call --local nacl.enc apassword
|
||||
|
||||
|
||||
Pillar files can include protected data that the salt master decrypts:
|
||||
|
||||
.. code-block:: jinja
|
||||
|
||||
pillarexample:
|
||||
user: root
|
||||
password1: {{salt.nacl.dec('DRB7Q6/X5gGSRCTpZyxS6hlbWj0llUA+uaVyvou3vJ4=')|json}}
|
||||
cert_key: {{salt.nacl.dec_file('/srv/salt/certs/example.com/key.nacl')|json}}
|
||||
cert_key2: {{salt.nacl.dec_file('salt:///certs/example.com/key.nacl')|json}}
|
||||
|
||||
Larger files like certificates can be encrypted with:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-call nacl.enc_file /tmp/cert.crt out=/tmp/cert.nacl
|
||||
# or more advanced
|
||||
cert=$(cat /tmp/cert.crt)
|
||||
salt-call --out=newline_values_only nacl.enc_pub data="$cert" > /tmp/cert.nacl
|
||||
|
||||
In Pillars rended with jinja be sure to include `|json` so line breaks are encoded:
|
||||
|
||||
.. code-block:: jinja
|
||||
|
||||
cert: "{{salt.nacl.dec('S2uogToXkgENz9...085KYt')|json}}"
|
||||
|
||||
In States rendered with jinja it is also good pratice to include `|json`:
|
||||
|
||||
.. code-block:: jinja
|
||||
|
||||
{{sls}} private key:
|
||||
file.managed:
|
||||
- name: /etc/ssl/private/cert.key
|
||||
- mode: 700
|
||||
- contents: "{{pillar['pillarexample']['cert_key']|json}}"
|
||||
|
||||
|
||||
Optional small program to encrypt data without needing salt modules.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
#!/bin/python3
|
||||
import sys, base64, libnacl.sealed
|
||||
pk = base64.b64decode('YOURPUBKEY')
|
||||
b = libnacl.sealed.SealedBox(pk)
|
||||
data = sys.stdin.buffer.read()
|
||||
print(base64.b64encode(b.encrypt(data)).decode())
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
echo 'apassword' | nacl_enc.py
|
||||
|
||||
'''
|
||||
|
||||
from __future__ import absolute_import
|
||||
import base64
|
||||
import os
|
||||
import salt.utils.files
|
||||
import salt.utils
|
||||
import salt.syspaths
|
||||
|
||||
|
||||
REQ_ERROR = None
|
||||
try:
|
||||
import libnacl.secret
|
||||
except ImportError as e:
|
||||
REQ_ERROR = 'libnacl import error, perhaps missing python libnacl package'
|
||||
import libnacl.sealed
|
||||
except (ImportError, OSError) as e:
|
||||
REQ_ERROR = 'libnacl import error, perhaps missing python libnacl package or should update.'
|
||||
|
||||
__virtualname__ = 'nacl'
|
||||
|
||||
|
@ -50,91 +175,286 @@ def _get_config(**kwargs):
|
|||
Return configuration
|
||||
'''
|
||||
config = {
|
||||
'key': None,
|
||||
'keyfile': None,
|
||||
'box_type': 'sealedbox',
|
||||
'sk': None,
|
||||
'sk_file': '/etc/salt/pki/master/nacl',
|
||||
'pk': None,
|
||||
'pk_file': '/etc/salt/pki/master/nacl.pub',
|
||||
}
|
||||
config_key = '{0}.config'.format(__virtualname__)
|
||||
try:
|
||||
config.update(__salt__['config.get'](config_key, {}))
|
||||
except (NameError, KeyError) as e:
|
||||
# likly using salt-run so fallback to __opts__
|
||||
config.update(__opts__.get(config_key, {}))
|
||||
for k in set(config) & set(kwargs):
|
||||
# pylint: disable=C0201
|
||||
for k in set(config.keys()) & set(kwargs.keys()):
|
||||
config[k] = kwargs[k]
|
||||
return config
|
||||
|
||||
|
||||
def _get_key(rstrip_newline=True, **kwargs):
|
||||
def _get_sk(**kwargs):
|
||||
'''
|
||||
Return key
|
||||
Return sk
|
||||
'''
|
||||
config = _get_config(**kwargs)
|
||||
key = config['key']
|
||||
keyfile = config['keyfile']
|
||||
if not key and keyfile:
|
||||
if not os.path.isfile(keyfile):
|
||||
raise Exception('file not found: {0}'.format(keyfile))
|
||||
with salt.utils.files.fopen(keyfile, 'rb') as keyf:
|
||||
key = keyf.read()
|
||||
key = config['sk']
|
||||
sk_file = config['sk_file']
|
||||
if not key and sk_file:
|
||||
with salt.utils.fopen(sk_file, 'rb') as keyf:
|
||||
key = str(keyf.read()).rstrip('\n')
|
||||
if key is None:
|
||||
raise Exception('no key found')
|
||||
key = str(key)
|
||||
if rstrip_newline:
|
||||
key = key.rstrip('\n')
|
||||
return key
|
||||
raise Exception('no key or sk_file found')
|
||||
return base64.b64decode(key)
|
||||
|
||||
|
||||
def keygen(keyfile=None):
|
||||
def _get_pk(**kwargs):
|
||||
'''
|
||||
Use libnacl to generate a private key
|
||||
Return pk
|
||||
'''
|
||||
config = _get_config(**kwargs)
|
||||
pubkey = config['pk']
|
||||
pk_file = config['pk_file']
|
||||
if not pubkey and pk_file:
|
||||
with salt.utils.fopen(pk_file, 'rb') as keyf:
|
||||
pubkey = str(keyf.read()).rstrip('\n')
|
||||
if pubkey is None:
|
||||
raise Exception('no pubkey or pk_file found')
|
||||
pubkey = str(pubkey)
|
||||
return base64.b64decode(pubkey)
|
||||
|
||||
|
||||
def keygen(sk_file=None, pk_file=None):
|
||||
'''
|
||||
Use libnacl to generate a keypair.
|
||||
|
||||
If no `sk_file` is defined return a keypair.
|
||||
|
||||
If only the `sk_file` is defined `pk_file` will use the same name with a postfix `.pub`.
|
||||
|
||||
When the `sk_file` is already existing, but `pk_file` is not. The `pk_file` will be generated
|
||||
using the `sk_file`.
|
||||
|
||||
CLI Examples:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-run nacl.keygen
|
||||
salt-run nacl.keygen keyfile=/root/.nacl
|
||||
salt-run --out=newline_values_only nacl.keygen > /root/.nacl
|
||||
salt-call nacl.keygen
|
||||
salt-call nacl.keygen sk_file=/etc/salt/pki/master/nacl
|
||||
salt-call nacl.keygen sk_file=/etc/salt/pki/master/nacl pk_file=/etc/salt/pki/master/nacl.pub
|
||||
salt-call --local nacl.keygen
|
||||
'''
|
||||
b = libnacl.secret.SecretBox()
|
||||
key = b.sk
|
||||
key = base64.b64encode(key)
|
||||
if keyfile:
|
||||
if os.path.isfile(keyfile):
|
||||
raise Exception('file already found: {0}'.format(keyfile))
|
||||
with salt.utils.files.fopen(keyfile, 'w') as keyf:
|
||||
keyf.write(key)
|
||||
return 'saved: {0}'.format(keyfile)
|
||||
return key
|
||||
if sk_file is None:
|
||||
kp = libnacl.public.SecretKey()
|
||||
return {'sk': base64.b64encode(kp.sk), 'pk': base64.b64encode(kp.pk)}
|
||||
|
||||
if pk_file is None:
|
||||
pk_file = '{0}.pub'.format(sk_file)
|
||||
|
||||
if sk_file and pk_file is None:
|
||||
if not os.path.isfile(sk_file):
|
||||
kp = libnacl.public.SecretKey()
|
||||
with salt.utils.fopen(sk_file, 'w') as keyf:
|
||||
keyf.write(base64.b64encode(kp.sk))
|
||||
if not salt.utils.is_windows():
|
||||
# chmod 0600 file
|
||||
os.chmod(sk_file, 1536)
|
||||
return 'saved sk_file: {0}'.format(sk_file)
|
||||
else:
|
||||
raise Exception('sk_file:{0} already exist.'.format(sk_file))
|
||||
|
||||
if sk_file is None and pk_file:
|
||||
raise Exception('sk_file: Must be set inorder to generate a public key.')
|
||||
|
||||
if os.path.isfile(sk_file) and os.path.isfile(pk_file):
|
||||
raise Exception('sk_file:{0} and pk_file:{1} already exist.'.format(sk_file, pk_file))
|
||||
|
||||
if os.path.isfile(sk_file) and not os.path.isfile(pk_file):
|
||||
# generate pk using the sk
|
||||
with salt.utils.fopen(sk_file, 'rb') as keyf:
|
||||
sk = str(keyf.read()).rstrip('\n')
|
||||
sk = base64.b64decode(sk)
|
||||
kp = libnacl.public.SecretKey(sk)
|
||||
with salt.utils.fopen(pk_file, 'w') as keyf:
|
||||
keyf.write(base64.b64encode(kp.pk))
|
||||
return 'saved pk_file: {0}'.format(pk_file)
|
||||
|
||||
kp = libnacl.public.SecretKey()
|
||||
with salt.utils.fopen(sk_file, 'w') as keyf:
|
||||
keyf.write(base64.b64encode(kp.sk))
|
||||
if not salt.utils.is_windows():
|
||||
# chmod 0600 file
|
||||
os.chmod(sk_file, 1536)
|
||||
with salt.utils.fopen(pk_file, 'w') as keyf:
|
||||
keyf.write(base64.b64encode(kp.pk))
|
||||
return 'saved sk_file:{0} pk_file: {1}'.format(sk_file, pk_file)
|
||||
|
||||
|
||||
def enc(data, **kwargs):
|
||||
'''
|
||||
Takes a key generated from `nacl.keygen` and encrypt some data.
|
||||
Alias to `{box_type}_encrypt`
|
||||
|
||||
box_type: secretbox, sealedbox(default)
|
||||
'''
|
||||
box_type = _get_config(**kwargs)['box_type']
|
||||
if box_type == 'sealedbox':
|
||||
return sealedbox_encrypt(data, **kwargs)
|
||||
if box_type == 'secretbox':
|
||||
return secretbox_encrypt(data, **kwargs)
|
||||
return sealedbox_encrypt(data, **kwargs)
|
||||
|
||||
|
||||
def enc_file(name, out=None, **kwargs):
|
||||
'''
|
||||
This is a helper function to encrypt a file and return its contents.
|
||||
|
||||
You can provide an optional output file using `out`
|
||||
|
||||
`name` can be a local file or when not using `salt-run` can be a url like `salt://`, `https://` etc.
|
||||
|
||||
CLI Examples:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-run nacl.enc datatoenc
|
||||
salt-run nacl.enc datatoenc keyfile=/root/.nacl
|
||||
salt-run nacl.enc datatoenc key='cKEzd4kXsbeCE7/nLTIqXwnUiD1ulg4NoeeYcCFpd9k='
|
||||
salt-run nacl.enc_file name=/tmp/id_rsa
|
||||
salt-call nacl.enc_file name=salt://crt/mycert out=/tmp/cert
|
||||
salt-run nacl.enc_file name=/tmp/id_rsa box_type=secretbox \
|
||||
sk_file=/etc/salt/pki/master/nacl.pub
|
||||
'''
|
||||
key = _get_key(**kwargs)
|
||||
sk = base64.b64decode(key)
|
||||
b = libnacl.secret.SecretBox(sk)
|
||||
return base64.b64encode(b.encrypt(data))
|
||||
try:
|
||||
data = __salt__['cp.get_file_str'](name)
|
||||
except Exception as e:
|
||||
# likly using salt-run so fallback to local filesystem
|
||||
with salt.utils.fopen(name, 'rb') as f:
|
||||
data = f.read()
|
||||
d = enc(data, **kwargs)
|
||||
if out:
|
||||
if os.path.isfile(out):
|
||||
raise Exception('file:{0} already exist.'.format(out))
|
||||
with salt.utils.fopen(out, 'wb') as f:
|
||||
f.write(d)
|
||||
return 'Wrote: {0}'.format(out)
|
||||
return d
|
||||
|
||||
|
||||
def dec(data, **kwargs):
|
||||
'''
|
||||
Takes a key generated from `nacl.keygen` and decrypt some data.
|
||||
Alias to `{box_type}_decrypt`
|
||||
|
||||
box_type: secretbox, sealedbox(default)
|
||||
'''
|
||||
box_type = _get_config(**kwargs)['box_type']
|
||||
if box_type == 'sealedbox':
|
||||
return sealedbox_decrypt(data, **kwargs)
|
||||
if box_type == 'secretbox':
|
||||
return secretbox_decrypt(data, **kwargs)
|
||||
return sealedbox_decrypt(data, **kwargs)
|
||||
|
||||
|
||||
def dec_file(name, out=None, **kwargs):
|
||||
'''
|
||||
This is a helper function to decrypt a file and return its contents.
|
||||
|
||||
You can provide an optional output file using `out`
|
||||
|
||||
`name` can be a local file or when not using `salt-run` can be a url like `salt://`, `https://` etc.
|
||||
|
||||
CLI Examples:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-run nacl.dec pEXHQM6cuaF7A=
|
||||
salt-run nacl.dec data='pEXHQM6cuaF7A=' keyfile=/root/.nacl
|
||||
salt-run nacl.dec data='pEXHQM6cuaF7A=' key='cKEzd4kXsbeCE7/nLTIqXwnUiD1ulg4NoeeYcCFpd9k='
|
||||
salt-run nacl.dec_file name=/tmp/id_rsa.nacl
|
||||
salt-call nacl.dec_file name=salt://crt/mycert.nacl out=/tmp/id_rsa
|
||||
salt-run nacl.dec_file name=/tmp/id_rsa.nacl box_type=secretbox \
|
||||
sk_file=/etc/salt/pki/master/nacl.pub
|
||||
'''
|
||||
key = _get_key(**kwargs)
|
||||
sk = base64.b64decode(key)
|
||||
b = libnacl.secret.SecretBox(key=sk)
|
||||
try:
|
||||
data = __salt__['cp.get_file_str'](name)
|
||||
except Exception as e:
|
||||
# likly using salt-run so fallback to local filesystem
|
||||
with salt.utils.fopen(name, 'rb') as f:
|
||||
data = f.read()
|
||||
d = dec(data, **kwargs)
|
||||
if out:
|
||||
if os.path.isfile(out):
|
||||
raise Exception('file:{0} already exist.'.format(out))
|
||||
with salt.utils.fopen(out, 'wb') as f:
|
||||
f.write(d)
|
||||
return 'Wrote: {0}'.format(out)
|
||||
return d
|
||||
|
||||
|
||||
def sealedbox_encrypt(data, **kwargs):
|
||||
'''
|
||||
Encrypt data using a public key generated from `nacl.keygen`.
|
||||
The encryptd data can be decrypted using `nacl.sealedbox_decrypt` only with the secret key.
|
||||
|
||||
CLI Examples:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-run nacl.sealedbox_encrypt datatoenc
|
||||
salt-call --local nacl.sealedbox_encrypt datatoenc pk_file=/etc/salt/pki/master/nacl.pub
|
||||
salt-call --local nacl.sealedbox_encrypt datatoenc pk='vrwQF7cNiNAVQVAiS3bvcbJUnF0cN6fU9YTZD9mBfzQ='
|
||||
'''
|
||||
pk = _get_pk(**kwargs)
|
||||
b = libnacl.sealed.SealedBox(pk)
|
||||
return base64.b64encode(b.encrypt(data))
|
||||
|
||||
|
||||
def sealedbox_decrypt(data, **kwargs):
|
||||
'''
|
||||
Decrypt data using a secret key that was encrypted using a public key with `nacl.sealedbox_encrypt`.
|
||||
|
||||
CLI Examples:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-call nacl.sealedbox_decrypt pEXHQM6cuaF7A=
|
||||
salt-call --local nacl.sealedbox_decrypt data='pEXHQM6cuaF7A=' sk_file=/etc/salt/pki/master/nacl
|
||||
salt-call --local nacl.sealedbox_decrypt data='pEXHQM6cuaF7A=' sk='YmFkcGFzcwo='
|
||||
'''
|
||||
if data is None:
|
||||
return None
|
||||
sk = _get_sk(**kwargs)
|
||||
keypair = libnacl.public.SecretKey(sk)
|
||||
b = libnacl.sealed.SealedBox(keypair)
|
||||
return b.decrypt(base64.b64decode(data))
|
||||
|
||||
|
||||
def secretbox_encrypt(data, **kwargs):
|
||||
'''
|
||||
Encrypt data using a secret key generated from `nacl.keygen`.
|
||||
The same secret key can be used to decrypt the data using `nacl.secretbox_decrypt`.
|
||||
|
||||
CLI Examples:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-run nacl.secretbox_encrypt datatoenc
|
||||
salt-call --local nacl.secretbox_encrypt datatoenc sk_file=/etc/salt/pki/master/nacl
|
||||
salt-call --local nacl.secretbox_encrypt datatoenc sk='YmFkcGFzcwo='
|
||||
'''
|
||||
sk = _get_sk(**kwargs)
|
||||
b = libnacl.secret.SecretBox(sk)
|
||||
return base64.b64encode(b.encrypt(data))
|
||||
|
||||
|
||||
def secretbox_decrypt(data, **kwargs):
|
||||
'''
|
||||
Decrypt data that was encrypted using `nacl.secretbox_encrypt` using the secret key
|
||||
that was generated from `nacl.keygen`.
|
||||
|
||||
CLI Examples:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-call nacl.secretbox_decrypt pEXHQM6cuaF7A=
|
||||
salt-call --local nacl.secretbox_decrypt data='pEXHQM6cuaF7A=' sk_file=/etc/salt/pki/master/nacl
|
||||
salt-call --local nacl.secretbox_decrypt data='pEXHQM6cuaF7A=' sk='YmFkcGFzcwo='
|
||||
'''
|
||||
if data is None:
|
||||
return None
|
||||
key = _get_sk(**kwargs)
|
||||
b = libnacl.secret.SecretBox(key=key)
|
||||
return b.decrypt(base64.b64decode(data))
|
||||
|
|
Loading…
Add table
Reference in a new issue