1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163
|
#!/usr/bin/env python
"""Transit methods module."""
from hvac import exceptions, utils
from hvac.api.vault_api_base import VaultApiBase
from hvac.constants import transit as transit_constants
DEFAULT_MOUNT_POINT = "transit"
class Transit(VaultApiBase):
"""Transit Secrets Engine (API).
Reference: https://www.vaultproject.io/api/secret/transit/index.html
"""
def create_key(
self,
name,
convergent_encryption=None,
derived=None,
exportable=None,
allow_plaintext_backup=None,
key_type=None,
mount_point=DEFAULT_MOUNT_POINT,
auto_rotate_period=None,
):
"""Create a new named encryption key of the specified type.
The values set here cannot be changed after key creation.
Supported methods:
POST: /{mount_point}/keys/{name}. Produces: 204 (empty body)
:param name: Specifies the name of the encryption key to create. This is specified as part of the URL.
:type name: str | unicode
:param convergent_encryption: If enabled, the key will support convergent encryption, where the same plaintext
creates the same ciphertext. This requires derived to be set to true. When enabled, each
encryption(/decryption/rewrap/datakey) operation will derive a nonce value rather than randomly generate it.
:type convergent_encryption: bool
:param derived: Specifies if key derivation is to be used. If enabled, all encrypt/decrypt requests to this
named key must provide a context which is used for key derivation.
:type derived: bool
:param exportable: Enables keys to be exportable. This allows for all the valid keys in the key ring to be
exported. Once set, this cannot be disabled.
:type exportable: bool
:param allow_plaintext_backup: If set, enables taking backup of named key in the plaintext format. Once set,
this cannot be disabled.
:type allow_plaintext_backup: bool
:param key_type: Specifies the type of key to create. The currently-supported types are:
* **aes256-gcm96**: AES-256 wrapped with GCM using a 96-bit nonce size AEAD
* **chacha20-poly1305**: ChaCha20-Poly1305 AEAD (symmetric, supports derivation and convergent encryption)
* **ed25519**: ED25519 (asymmetric, supports derivation).
* **ecdsa-p256**: ECDSA using the P-256 elliptic curve (asymmetric)
* **ecdsa-p384**: ECDSA using the P-384 elliptic curve (asymmetric)
* **ecdsa-p521**: ECDSA using the P-521 elliptic curve (asymmetric)
* **rsa-2048**: RSA with bit size of 2048 (asymmetric)
* **rsa-3072**: RSA with bit size of 3072 (asymmetric)
* **rsa-4096**: RSA with bit size of 4096 (asymmetric)
:type key_type: str | unicode
:param mount_point: The "path" the method/backend was mounted on.
:type mount_point: str | unicode
:param auto_rotate_period: The period at which this key should be rotated automatically. Requires Vault 1.10.x or higher.
:type auto_rotate_period: str | unicode
:return: The response of the request.
:rtype: requests.Response
"""
if convergent_encryption and not derived:
raise exceptions.ParamValidationError(
"derived must be set to True when convergent_encryption is True"
)
if key_type is not None and key_type not in transit_constants.ALLOWED_KEY_TYPES:
error_msg = 'invalid key_type argument provided "{arg}", supported types: "{allowed_types}"'
raise exceptions.ParamValidationError(
error_msg.format(
arg=key_type,
allowed_types=", ".join(transit_constants.ALLOWED_KEY_TYPES),
)
)
params = utils.remove_nones(
{
"convergent_encryption": convergent_encryption,
"derived": derived,
"exportable": exportable,
"allow_plaintext_backup": allow_plaintext_backup,
"type": key_type,
"auto_rotate_period": auto_rotate_period,
}
)
api_path = utils.format_url(
"/v1/{mount_point}/keys/{name}",
mount_point=mount_point,
name=name,
)
return self._adapter.post(
url=api_path,
json=params,
)
def read_key(self, name, mount_point=DEFAULT_MOUNT_POINT):
"""Read information about a named encryption key.
The keys object shows the creation time of each key version; the values are not the keys themselves. Depending
on the type of key, different information may be returned, e.g. an asymmetric key will return its public key in
a standard format for the type.
Supported methods:
GET: /{mount_point}/keys/{name}. Produces: 200 application/json
:param name: Specifies the name of the encryption key to read. This is specified as part of the URL.
:type name: str | unicode
:param mount_point: The "path" the method/backend was mounted on.
:type mount_point: str | unicode
:return: The JSON response of the read_key request.
:rtype: dict
"""
api_path = utils.format_url(
"/v1/{mount_point}/keys/{name}",
mount_point=mount_point,
name=name,
)
return self._adapter.get(
url=api_path,
)
def list_keys(self, mount_point=DEFAULT_MOUNT_POINT):
"""List keys (if there are any).
Only the key names are returned (not the actual keys themselves).
An exception is thrown if there are no keys.
Supported methods:
LIST: /{mount_point}/keys. Produces: 200 application/json
:param mount_point: The "path" the method/backend was mounted on.
:type mount_point: str | unicode
:return: The JSON response of the request.
:rtype: dict
"""
api_path = utils.format_url("/v1/{mount_point}/keys", mount_point=mount_point)
return self._adapter.list(url=api_path)
def delete_key(self, name, mount_point=DEFAULT_MOUNT_POINT):
"""Delete a named encryption key.
It will no longer be possible to decrypt any data encrypted with the named key. Because this is a potentially
catastrophic operation, the deletion_allowed tunable must be set in the key's /config endpoint.
Supported methods:
DELETE: /{mount_point}/keys/{name}. Produces: 204 (empty body)
:param name: Specifies the name of the encryption key to delete. This is specified as part of the URL.
:type name: str | unicode
:param mount_point: The "path" the method/backend was mounted on.
:type mount_point: str | unicode
:return: The response of the request.
:rtype: requests.Response
"""
api_path = utils.format_url(
"/v1/{mount_point}/keys/{name}",
mount_point=mount_point,
name=name,
)
return self._adapter.delete(
url=api_path,
)
def update_key_configuration(
self,
name,
min_decryption_version=None,
min_encryption_version=None,
deletion_allowed=None,
exportable=None,
allow_plaintext_backup=None,
mount_point=DEFAULT_MOUNT_POINT,
auto_rotate_period=None,
):
"""Tune configuration values for a given key.
These values are returned during a read operation on the named key.
Supported methods:
POST: /{mount_point}/keys/{name}/config. Produces: 204 (empty body)
:param name: Specifies the name of the encryption key to update configuration for.
:type name: str | unicode
:param min_decryption_version: Specifies the minimum version of ciphertext allowed to be decrypted. Adjusting
this as part of a key rotation policy can prevent old copies of ciphertext from being decrypted, should they
fall into the wrong hands. For signatures, this value controls the minimum version of signature that can be
verified against. For HMACs, this controls the minimum version of a key allowed to be used as the key for
verification.
:type min_decryption_version: int
:param min_encryption_version: Specifies the minimum version of the key that can be used to encrypt plaintext,
sign payloads, or generate HMACs. Must be 0 (which will use the latest version) or a value greater or equal
to min_decryption_version.
:type min_encryption_version: int
:param deletion_allowed: Specifies if the key is allowed to be deleted.
:type deletion_allowed: bool
:param exportable: Enables keys to be exportable. This allows for all the valid keys in the key ring to be
exported. Once set, this cannot be disabled.
:type exportable: bool
:param allow_plaintext_backup: If set, enables taking backup of named key in the plaintext format. Once set,
this cannot be disabled.
:type allow_plaintext_backup: bool
:param mount_point: The "path" the method/backend was mounted on.
:type mount_point: str | unicode
:param auto_rotate_period: The period at which this key should be rotated automatically. Requires Vault 1.10.x or higher.
:type auto_rotate_period: str | unicode
:return: The response of the request.
:rtype: requests.Response
"""
if min_encryption_version is not None and min_decryption_version is not None:
if (
min_encryption_version != 0
and min_encryption_version <= min_decryption_version
):
raise exceptions.ParamValidationError(
"min_encryption_version must be 0 or > min_decryption_version"
)
params = utils.remove_nones(
{
"min_decryption_version": min_decryption_version,
"min_encryption_version": min_encryption_version,
"deletion_allowed": deletion_allowed,
"exportable": exportable,
"allow_plaintext_backup": allow_plaintext_backup,
"auto_rotate_period": auto_rotate_period,
}
)
api_path = utils.format_url(
"/v1/{mount_point}/keys/{name}/config",
mount_point=mount_point,
name=name,
)
return self._adapter.post(
url=api_path,
json=params,
)
def rotate_key(self, name, mount_point=DEFAULT_MOUNT_POINT):
"""Rotate the version of the named key.
After rotation, new plaintext requests will be encrypted with the new version of the key. To upgrade ciphertext
to be encrypted with the latest version of the key, use the rewrap endpoint. This is only supported with keys
that support encryption and decryption operations.
Supported methods:
POST: /{mount_point}/keys/{name}/rotate. Produces: 204 (empty body)
:param name: Specifies the name of the key to read information about. This is specified as part of the URL.
:type name: str | unicode
:param mount_point: The "path" the method/backend was mounted on.
:type mount_point: str | unicode
:return: The response of the request.
:rtype: requests.Response
"""
api_path = utils.format_url(
"/v1/{mount_point}/keys/{name}/rotate",
mount_point=mount_point,
name=name,
)
return self._adapter.post(
url=api_path,
)
def export_key(self, name, key_type, version=None, mount_point=DEFAULT_MOUNT_POINT):
"""Return the named key.
The keys object shows the value of the key for each version. If version is specified, the specific version will
be returned. If latest is provided as the version, the current key will be provided. Depending on the type of
key, different information may be returned. The key must be exportable to support this operation and the version
must still be valid.
Supported methods:
GET: /{mount_point}/export/{key_type}/{name}(/{version}). Produces: 200 application/json
:param name: Specifies the name of the key to read information about. This is specified as part of the URL.
:type name: str | unicode
:param key_type: Specifies the type of the key to export. This is specified as part of the URL. Valid values are:
encryption-key
signing-key
hmac-key
:type key_type: str | unicode
:param version: Specifies the version of the key to read. If omitted, all versions of the key will be returned.
If the version is set to latest, the current key will be returned.
:type version: str | unicode
:param mount_point: The "path" the method/backend was mounted on.
:type mount_point: str | unicode
:return: The JSON response of the request.
:rtype: dict
"""
if key_type not in transit_constants.ALLOWED_EXPORT_KEY_TYPES:
error_msg = 'invalid key_type argument provided "{arg}", supported types: "{allowed_types}"'
raise exceptions.ParamValidationError(
error_msg.format(
arg=key_type,
allowed_types=", ".join(transit_constants.ALLOWED_EXPORT_KEY_TYPES),
)
)
api_path = utils.format_url(
"/v1/{mount_point}/export/{key_type}/{name}",
mount_point=mount_point,
key_type=key_type,
name=name,
)
if version is not None:
api_path = self._adapter.urljoin(api_path, version)
return self._adapter.get(
url=api_path,
)
def encrypt_data(
self,
name,
plaintext=None,
context=None,
key_version=None,
nonce=None,
batch_input=None,
type=None,
convergent_encryption=None,
mount_point=DEFAULT_MOUNT_POINT,
associated_data=None,
):
"""Encrypt the provided plaintext using the named key.
This path supports the create and update policy capabilities as follows: if the user has the create capability
for this endpoint in their policies, and the key does not exist, it will be upserted with default values
(whether the key requires derivation depends on whether the context parameter is empty or not). If the user only
has update capability and the key does not exist, an error will be returned.
Supported methods:
POST: /{mount_point}/encrypt/{name}. Produces: 200 application/json
:param name: Specifies the name of the encryption key to encrypt against. This is specified as part of the URL.
:type name: str | unicode
:param plaintext: Specifies base64 encoded plaintext to be encoded. Ignored if ``batch_input`` is set, otherwise required.
:type plaintext: str | unicode
:param context: Specifies the base64 encoded context for key derivation. This is required if key derivation is
enabled for this key.
:type context: str | unicode
:param associated_data: Specifies base64 encoded associated data (also known as additional data or AAD) to also be authenticated
with AEAD ciphers (aes128-gcm96, aes256-gcm, and chacha20-poly1305)
:type associated_data: str | unicode
:param key_version: Specifies the version of the key to use for encryption. If not set, uses the latest version.
Must be greater than or equal to the key's min_encryption_version, if set.
:type key_version: int
:param nonce: Specifies the base64 encoded nonce value. This must be provided if convergent encryption is
enabled for this key and the key was generated with Vault 0.6.1. Not required for keys created in 0.6.2+.
The value must be exactly 96 bits (12 bytes) long and the user must ensure that for any given context (and
thus, any given encryption key) this nonce value is never reused.
:type nonce: str | unicode
:param batch_input: Specifies a list of items to be encrypted in a single batch. When this parameter is set, if
the parameters 'plaintext', 'context' and 'nonce' are also set, they will be ignored. The format for the
input is: [dict(context="b64_context", plaintext="b64_plaintext"), ...]
:type batch_input: List[dict]
:param type: This parameter is required when encryption key is expected to be created. When performing an
upsert operation, the type of key to create.
:type type: str | unicode
:param convergent_encryption: This parameter will only be used when a key is expected to be created. Whether to
support convergent encryption. This is only supported when using a key with key derivation enabled and will
require all requests to carry both a context and 96-bit (12-byte) nonce. The given nonce will be used in
place of a randomly generated nonce. As a result, when the same context and nonce are supplied, the same
ciphertext is generated. It is very important when using this mode that you ensure that all nonces are
unique for a given context. Failing to do so will severely impact the ciphertext's security.
:type convergent_encryption: str | unicode
:param mount_point: The "path" the method/backend was mounted on.
:type mount_point: str | unicode
:return: The JSON response of the request.
:rtype: dict
"""
if plaintext is None and batch_input is None:
raise ValueError("plaintext must be specified unless batch_input is set")
params = {
"plaintext": plaintext,
}
params.update(
utils.remove_nones(
{
"context": context,
"associated_data": associated_data,
"key_version": key_version,
"nonce": nonce,
"batch_input": batch_input,
"type": type,
"convergent_encryption": convergent_encryption,
}
)
)
api_path = utils.format_url(
"/v1/{mount_point}/encrypt/{name}",
mount_point=mount_point,
name=name,
)
return self._adapter.post(
url=api_path,
json=params,
)
def decrypt_data(
self,
name,
ciphertext=None,
context=None,
nonce=None,
batch_input=None,
mount_point=DEFAULT_MOUNT_POINT,
associated_data=None,
):
"""Decrypt the provided ciphertext using the named key.
Supported methods:
POST: /{mount_point}/decrypt/{name}. Produces: 200 application/json
:param name: Specifies the name of the encryption key to decrypt against. This is specified as part of the URL.
:type name: str | unicode
:param ciphertext: The ciphertext to decrypt. Ignored if ``batch_input`` is set, otherwise required.
:type ciphertext: str | unicode
:param context: Specifies the base64 encoded context for key derivation. This is required if key derivation is
enabled.
:type context: str | unicode
:param associated_data: Specifies base64 encoded associated data (also known as additional data or AAD) to also
be authenticated with AEAD ciphers (aes128-gcm96, aes256-gcm, and chacha20-poly1305)
:type associated_data: str | unicode
:param nonce: Specifies a base64 encoded nonce value used during encryption. Must be provided if convergent
encryption is enabled for this key and the key was generated with Vault 0.6.1. Not required for keys created
in 0.6.2+.
:type nonce: str | unicode
:param batch_input: Specifies a list of items to be decrypted in a single batch. When this parameter is set, if
the parameters 'ciphertext', 'context' and 'nonce' are also set, they will be ignored. Format for the input
goes like this: [dict(context="b64_context", ciphertext="b64_plaintext"), ...]
:type batch_input: List[dict]
:param mount_point: The "path" the method/backend was mounted on.
:type mount_point: str | unicode
:return: The JSON response of the request.
:rtype: dict
"""
if ciphertext is None and batch_input is None:
raise ValueError("ciphertext must be specified unless batch_input is set")
params = {
"ciphertext": ciphertext,
}
params.update(
utils.remove_nones(
{
"context": context,
"associated_data": associated_data,
"nonce": nonce,
"batch_input": batch_input,
}
)
)
api_path = utils.format_url(
"/v1/{mount_point}/decrypt/{name}",
mount_point=mount_point,
name=name,
)
return self._adapter.post(
url=api_path,
json=params,
)
def rewrap_data(
self,
name,
ciphertext,
context=None,
key_version=None,
nonce=None,
batch_input=None,
mount_point=DEFAULT_MOUNT_POINT,
):
"""Rewrap the provided ciphertext using the latest version of the named key.
Because this never returns plaintext, it is possible to delegate this functionality to untrusted users or scripts.
Supported methods:
POST: /{mount_point}/rewrap/{name}. Produces: 200 application/json
:param name: Specifies the name of the encryption key to re-encrypt against. This is specified as part of the URL.
:type name: str | unicode
:param ciphertext: Specifies the ciphertext to re-encrypt.
:type ciphertext: str | unicode
:param context: Specifies the base64 encoded context for key derivation. This is required if key derivation is
enabled.
:type context: str | unicode
:param key_version: Specifies the version of the key to use for the operation. If not set, uses the latest
version. Must be greater than or equal to the key's min_encryption_version, if set.
:type key_version: int
:param nonce: Specifies a base64 encoded nonce value used during encryption. Must be provided if convergent
encryption is enabled for this key and the key was generated with Vault 0.6.1. Not required for keys created
in 0.6.2+.
:type nonce: str | unicode
:param batch_input: Specifies a list of items to be decrypted in a single batch. When this parameter is set, if
the parameters 'ciphertext', 'context' and 'nonce' are also set, they will be ignored. Format for the input
goes like this: [dict(context="b64_context", ciphertext="b64_plaintext"), ...]
:type batch_input: List[dict]
:param mount_point: The "path" the method/backend was mounted on.
:type mount_point: str | unicode
:return: The JSON response of the request.
:rtype: dict
"""
params = {
"ciphertext": ciphertext,
}
params.update(
utils.remove_nones(
{
"context": context,
"key_version": key_version,
"nonce": nonce,
"batch_input": batch_input,
}
)
)
api_path = utils.format_url(
"/v1/{mount_point}/rewrap/{name}",
mount_point=mount_point,
name=name,
)
return self._adapter.post(
url=api_path,
json=params,
)
def generate_data_key(
self,
name,
key_type,
context=None,
nonce=None,
bits=None,
mount_point=DEFAULT_MOUNT_POINT,
):
"""Generates a new high-entropy key and the value encrypted with the named key.
Optionally return the plaintext of the key as well. Whether plaintext is returned depends on the path; as a
result, you can use Vault ACL policies to control whether a user is allowed to retrieve the plaintext value of a
key. This is useful if you want an untrusted user or operation to generate keys that are then made available to
trusted users.
Supported methods:
POST: /{mount_point}/datakey/{key_type}/{name}. Produces: 200 application/json
:param name: Specifies the name of the encryption key to use to encrypt the datakey. This is specified as part
of the URL.
:type name: str | unicode
:param key_type: Specifies the type of key to generate. If plaintext, the plaintext key will be returned along
with the ciphertext. If wrapped, only the ciphertext value will be returned. This is specified as part of
the URL.
:type key_type: str | unicode
:param context: Specifies the key derivation context, provided as a base64-encoded string. This must be provided
if derivation is enabled.
:type context: str | unicode
:param nonce: Specifies a nonce value, provided as base64 encoded. Must be provided if convergent encryption is
enabled for this key and the key was generated with Vault 0.6.1. Not required for keys created in 0.6.2+.
The value must be exactly 96 bits (12 bytes) long and the user must ensure that for any given context (and
thus, any given encryption key) this nonce value is never reused.
:type nonce: str | unicode
:param bits: Specifies the number of bits in the desired key. Can be 128, 256, or 512.
:type bits: int
:param mount_point: The "path" the method/backend was mounted on.
:type mount_point: str | unicode
:return: The JSON response of the request.
:rtype: dict
"""
if key_type not in transit_constants.ALLOWED_DATA_KEY_TYPES:
error_msg = 'invalid key_type argument provided "{arg}", supported types: "{allowed_types}"'
raise exceptions.ParamValidationError(
error_msg.format(
arg=key_type,
allowed_types=", ".join(transit_constants.ALLOWED_DATA_KEY_TYPES),
)
)
if bits is not None and bits not in transit_constants.ALLOWED_DATA_KEY_BITS:
error_msg = 'invalid bits argument provided "{arg}", supported values: "{allowed_values}"'
raise exceptions.ParamValidationError(
error_msg.format(
arg=bits,
allowed_values=", ".join(
[str(b) for b in transit_constants.ALLOWED_DATA_KEY_BITS]
),
)
)
params = utils.remove_nones(
{
"context": context,
"nonce": nonce,
"bits": bits,
}
)
api_path = utils.format_url(
"/v1/{mount_point}/datakey/{key_type}/{name}",
mount_point=mount_point,
key_type=key_type,
name=name,
)
return self._adapter.post(
url=api_path,
json=params,
)
def generate_random_bytes(
self, n_bytes=None, output_format=None, mount_point=DEFAULT_MOUNT_POINT
):
"""Return high-quality random bytes of the specified length.
Supported methods:
POST: /{mount_point}/random(/{bytes}). Produces: 200 application/json
:param n_bytes: Specifies the number of bytes to return. This value can be specified either in the request body,
or as a part of the URL.
:type n_bytes: int
:param output_format: Specifies the output encoding. Valid options are hex or base64.
:type output_format: str | unicode
:param mount_point: The "path" the method/backend was mounted on.
:type mount_point: str | unicode
:return: The JSON response of the request.
:rtype: dict
"""
params = utils.remove_nones(
{
"bytes": n_bytes,
"format": output_format,
}
)
api_path = utils.format_url("/v1/{mount_point}/random", mount_point=mount_point)
return self._adapter.post(
url=api_path,
json=params,
)
def hash_data(
self,
hash_input,
algorithm=None,
output_format=None,
mount_point=DEFAULT_MOUNT_POINT,
):
"""Return the cryptographic hash of given data using the specified algorithm.
Supported methods:
POST: /{mount_point}/hash(/{algorithm}). Produces: 200 application/json
:param hash_input: Specifies the base64 encoded input data.
:type hash_input: str | unicode
:param algorithm: Specifies the hash algorithm to use. This can also be specified as part of the URL.
Currently-supported algorithms are: sha2-224, sha2-256, sha2-384, sha2-512
:type algorithm: str | unicode
:param output_format: Specifies the output encoding. This can be either hex or base64.
:type output_format: str | unicode
:param mount_point: The "path" the method/backend was mounted on.
:type mount_point: str | unicode
:return: The JSON response of the request.
:rtype: dict
"""
if (
algorithm is not None
and algorithm not in transit_constants.ALLOWED_HASH_DATA_ALGORITHMS
):
error_msg = 'invalid algorithm argument provided "{arg}", supported types: "{allowed_types}"'
raise exceptions.ParamValidationError(
error_msg.format(
arg=algorithm,
allowed_types=", ".join(
transit_constants.ALLOWED_HASH_DATA_ALGORITHMS
),
)
)
if (
output_format is not None
and output_format not in transit_constants.ALLOWED_HASH_DATA_FORMATS
):
error_msg = 'invalid output_format argument provided "{arg}", supported types: "{allowed_types}"'
raise exceptions.ParamValidationError(
error_msg.format(
arg=output_format,
allowed_types=", ".join(
transit_constants.ALLOWED_HASH_DATA_FORMATS
),
)
)
params = {
"input": hash_input,
}
params.update(
utils.remove_nones(
{
"algorithm": algorithm,
"format": output_format,
}
)
)
api_path = utils.format_url("/v1/{mount_point}/hash", mount_point=mount_point)
return self._adapter.post(
url=api_path,
json=params,
)
def generate_hmac(
self,
name,
hash_input,
key_version=None,
algorithm=None,
mount_point=DEFAULT_MOUNT_POINT,
):
"""Return the digest of given data using the specified hash algorithm and the named key.
The key can be of any type supported by transit; the raw key will be marshaled into bytes to be used for the
HMAC function. If the key is of a type that supports rotation, the latest (current) version will be used.
Supported methods:
POST: /{mount_point}/hmac/{name}(/{algorithm}). Produces: 200 application/json
:param name: Specifies the name of the encryption key to generate hmac against. This is specified as part of the
URL.
:type name: str | unicode
:param hash_input: Specifies the base64 encoded input data.
:type input: str | unicode
:param key_version: Specifies the version of the key to use for the operation. If not set, uses the latest
version. Must be greater than or equal to the key's min_encryption_version, if set.
:type key_version: int
:param algorithm: Specifies the hash algorithm to use. This can also be specified as part of the URL.
Currently-supported algorithms are: sha2-224, sha2-256, sha2-384, sha2-512
:type algorithm: str | unicode
:param mount_point: The "path" the method/backend was mounted on.
:type mount_point: str | unicode
:return: The JSON response of the request.
:rtype: dict
"""
if (
algorithm is not None
and algorithm not in transit_constants.ALLOWED_HASH_DATA_ALGORITHMS
):
error_msg = 'invalid algorithm argument provided "{arg}", supported types: "{allowed_types}"'
raise exceptions.ParamValidationError(
error_msg.format(
arg=algorithm,
allowed_types=", ".join(
transit_constants.ALLOWED_HASH_DATA_ALGORITHMS
),
)
)
params = {
"input": hash_input,
}
params.update(
utils.remove_nones(
{
"key_version": key_version,
"algorithm": algorithm,
}
)
)
api_path = utils.format_url(
"/v1/{mount_point}/hmac/{name}",
mount_point=mount_point,
name=name,
)
return self._adapter.post(
url=api_path,
json=params,
)
def sign_data(
self,
name,
hash_input=None,
key_version=None,
hash_algorithm=None,
context=None,
prehashed=None,
signature_algorithm=None,
marshaling_algorithm=None,
salt_length=None,
mount_point=DEFAULT_MOUNT_POINT,
batch_input=None,
):
"""Return the cryptographic signature of the given data using the named key and the specified hash algorithm.
The key must be of a type that supports signing.
Supported methods:
POST: /{mount_point}/sign/{name}(/{hash_algorithm}). Produces: 200 application/json
:param name: Specifies the name of the encryption key to use for signing. This is specified as part of the URL.
:type name: str | unicode
:param hash_input: Specifies the base64 encoded input data.
This parameter is mutually exclusive with the ``batch_results`` parameter, but one of them must be supplied.
If both are set, or neither are set, an exception will be raised.
:type hash_input: str | unicode
:param key_version: Specifies the version of the key to use for signing. If not set, uses the latest version.
Must be greater than or equal to the key's min_encryption_version, if set.
:type key_version: int
:param hash_algorithm: Specifies the hash algorithm to use for supporting key types (notably, not including
ed25519 which specifies its own hash algorithm). This can also be specified as part of the URL.
Currently-supported algorithms are: sha2-224, sha2-256, sha2-384, sha2-512
:type hash_algorithm: str | unicode
:param context: Base64 encoded context for key derivation. Required if key derivation is enabled; currently only
available with ed25519 keys.
:type context: str | unicode
:param prehashed: Set to true when the input is already hashed. If the key type is rsa-2048 or rsa-4096, then
the algorithm used to hash the input should be indicated by the hash_algorithm parameter. Just as the value
to sign should be the base64-encoded representation of the exact binary data you want signed, when set, input
is expected to be base64-encoded binary hashed data, not hex-formatted. (As an example, on the command line,
you could generate a suitable input via openssl dgst -sha256 -binary | base64.)
:type prehashed: bool
:param signature_algorithm: When using a RSA key, specifies the RSA signature algorithm to use for signing.
Supported signature types are: pss, pkcs1v15
:type signature_algorithm: str | unicode
:param marshaling_algorithm: Specifies the way in which the signature should be marshaled. This currently only applies to ECDSA keys.
Supported types are: asn1, jws
:type marshaling_algorithm: str | unicode
:param salt_length: The salt length used to sign. Currently only applies to the RSA PSS signature scheme.
Options are 'auto' (the default used by Golang, causing the salt to be as large as possible when signing),
'hash' (causes the salt length to equal the length of the hash used in the signature),
or an integer between the minimum and the maximum permissible salt lengths for the given RSA key size.
Defaults to 'auto'.
:type salt_length: str | unicode
:param mount_point: The "path" the method/backend was mounted on.
:type mount_point: str | unicode
:param batch_input: Specifies a list of items for processing.
Any batch output will preserve the order of the batch input.
If the input data value of an item is invalid, the corresponding item in the ``batch_results``
will have the key ``error`` with a value describing the error.
This parameter is mutually exclusive with the ``hash_input`` parameter, but one of them must be supplied.
If both are set, or neither are set, an exception will be raised.
Responses are returned in the ``batch_results`` array component of the ``data`` element of the response.
:type batch_input: List[Dict[str, str]]
:return: The JSON response of the request.
:rtype: dict
"""
if (
hash_algorithm is not None
and hash_algorithm not in transit_constants.ALLOWED_HASH_DATA_ALGORITHMS
):
error_msg = 'invalid hash_algorithm argument provided "{arg}", supported types: "{allowed_types}"'
raise exceptions.ParamValidationError(
error_msg.format(
arg=hash_algorithm,
allowed_types=", ".join(
transit_constants.ALLOWED_HASH_DATA_ALGORITHMS
),
)
)
if (
signature_algorithm is not None
and signature_algorithm
not in transit_constants.ALLOWED_SIGNATURE_ALGORITHMS
):
error_msg = 'invalid signature_algorithm argument provided "{arg}", supported types: "{allowed_types}"'
raise exceptions.ParamValidationError(
error_msg.format(
arg=signature_algorithm,
allowed_types=", ".join(
transit_constants.ALLOWED_SIGNATURE_ALGORITHMS
),
)
)
if (
marshaling_algorithm is not None
and marshaling_algorithm
not in transit_constants.ALLOWED_MARSHALING_ALGORITHMS
):
error_msg = 'invalid marshaling_algorithm argument provided "{arg}", supported types: "{allowed_types}"'
raise exceptions.ParamValidationError(
error_msg.format(
arg=marshaling_algorithm,
allowed_types=", ".join(
transit_constants.ALLOWED_MARSHALING_ALGORITHMS
),
)
)
if (
salt_length is not None
and not transit_constants.ALLOWED_SALT_LENGTHS.fullmatch(salt_length)
):
error_msg = 'invalid salt_length argument provided "{arg}", supported types: "{allowed_types}"'
raise exceptions.ParamValidationError(
error_msg.format(
arg=salt_length,
allowed_types=transit_constants.ALLOWED_SALT_LENGTHS.pattern,
)
)
if hash_input is None and batch_input is None:
error_msg = "Invalid parameter combination: Please provide only one of the following parameters: 'hash_input' or 'batch_input'."
raise exceptions.ParamValidationError(message=error_msg)
if hash_input is not None and batch_input is not None:
error_msg = "Invalid parameter combination: 'hash_input' or 'batch_input' should be provided, not both."
raise exceptions.ParamValidationError(message=error_msg)
params = {
"input": hash_input,
}
params.update(
utils.remove_nones(
{
"key_version": key_version,
"hash_algorithm": hash_algorithm,
"context": context,
"prehashed": prehashed,
"signature_algorithm": signature_algorithm,
"marshaling_algorithm": marshaling_algorithm,
"salt_length": salt_length,
"batch_input": batch_input,
}
)
)
api_path = utils.format_url(
"/v1/{mount_point}/sign/{name}",
mount_point=mount_point,
name=name,
)
return self._adapter.post(
url=api_path,
json=params,
)
def verify_signed_data(
self,
name,
hash_input,
signature=None,
hmac=None,
hash_algorithm=None,
context=None,
prehashed=None,
signature_algorithm=None,
salt_length=None,
marshaling_algorithm=None,
mount_point=DEFAULT_MOUNT_POINT,
):
"""Return whether the provided signature is valid for the given data.
Supported methods:
POST: /{mount_point}/verify/{name}(/{hash_algorithm}). Produces: 200 application/json
:param name: Specifies the name of the encryption key that was used to generate the signature or HMAC.
:type name: str | unicode
:param hash_input: Specifies the base64 encoded input data.
:type input: str | unicode
:param signature: Specifies the signature output from the /transit/sign function. Either this must be supplied
or hmac must be supplied.
:type signature: str | unicode
:param hmac: Specifies the signature output from the /transit/hmac function. Either this must be supplied or
signature must be supplied.
:type hmac: str | unicode
:param hash_algorithm: Specifies the hash algorithm to use. This can also be specified as part of the URL.
Currently-supported algorithms are: sha2-224, sha2-256, sha2-384, sha2-512
:type hash_algorithm: str | unicode
:param context: Base64 encoded context for key derivation. Required if key derivation is enabled; currently only
available with ed25519 keys.
:type context: str | unicode
:param prehashed: Set to true when the input is already hashed. If the key type is rsa-2048 or rsa-4096, then
the algorithm used to hash the input should be indicated by the hash_algorithm parameter.
:type prehashed: bool
:param signature_algorithm: When using a RSA key, specifies the RSA signature algorithm to use for signature
verification. Supported signature types are: pss, pkcs1v15
:type signature_algorithm: str | unicode
:param marshaling_algorithm: Specifies the way in which the signature should be marshaled. This currently only applies to ECDSA keys.
Supported types are: asn1, jws
:type marshaling_algorithm: str | unicode
:param salt_length: The salt length used to sign. Currently only applies to the RSA PSS signature scheme.
Options are 'auto' (the default used by Golang, causing the salt to be as large as possible when signing),
'hash' (causes the salt length to equal the length of the hash used in the signature),
or an integer between the minimum and the maximum permissible salt lengths for the given RSA key size.
Defaults to 'auto'.
:type salt_length: str | unicode
:param mount_point: The "path" the method/backend was mounted on.
:type mount_point: str | unicode
:return: The JSON response of the request.
:rtype: dict
"""
if (signature is None and hmac is None) or (
signature is not None and hmac is not None
):
error_msg = 'either "signature" or "hmac" argument (but not both) must be provided to verify signature'
raise exceptions.ParamValidationError(error_msg)
if (
hash_algorithm is not None
and hash_algorithm not in transit_constants.ALLOWED_HASH_DATA_ALGORITHMS
):
error_msg = 'invalid hash_algorithm argument provided "{arg}", supported types: "{allowed_types}"'
raise exceptions.ParamValidationError(
error_msg.format(
arg=hash_algorithm,
allowed_types=", ".join(
transit_constants.ALLOWED_HASH_DATA_ALGORITHMS
),
)
)
if (
signature_algorithm is not None
and signature_algorithm
not in transit_constants.ALLOWED_SIGNATURE_ALGORITHMS
):
error_msg = 'invalid signature_algorithm argument provided "{arg}", supported types: "{allowed_types}"'
raise exceptions.ParamValidationError(
error_msg.format(
arg=signature_algorithm,
allowed_types=", ".join(
transit_constants.ALLOWED_SIGNATURE_ALGORITHMS
),
)
)
if (
marshaling_algorithm is not None
and marshaling_algorithm
not in transit_constants.ALLOWED_MARSHALING_ALGORITHMS
):
error_msg = 'invalid marshaling_algorithm argument provided "{arg}", supported types: "{allowed_types}"'
raise exceptions.ParamValidationError(
error_msg.format(
arg=marshaling_algorithm,
allowed_types=", ".join(
transit_constants.ALLOWED_MARSHALING_ALGORITHMS
),
)
)
if (
salt_length is not None
and not transit_constants.ALLOWED_SALT_LENGTHS.fullmatch(salt_length)
):
error_msg = 'invalid salt_length argument provided "{arg}", supported types: "{allowed_types}"'
raise exceptions.ParamValidationError(
error_msg.format(
arg=salt_length,
allowed_types=transit_constants.ALLOWED_SALT_LENGTHS.pattern,
)
)
params = {
"name": name,
"input": hash_input,
}
params.update(
utils.remove_nones(
{
"hash_algorithm": hash_algorithm,
"signature": signature,
"hmac": hmac,
"context": context,
"prehashed": prehashed,
"signature_algorithm": signature_algorithm,
"marshaling_algorithm": marshaling_algorithm,
"salt_length": salt_length,
}
)
)
api_path = utils.format_url(
"/v1/{mount_point}/verify/{name}", mount_point=mount_point, name=name
)
return self._adapter.post(
url=api_path,
json=params,
)
def backup_key(self, name, mount_point=DEFAULT_MOUNT_POINT):
"""Return a plaintext backup of a named key.
The backup contains all the configuration data and keys of all the versions along with the HMAC key. The
response from this endpoint can be used with the /restore endpoint to restore the key.
Supported methods:
GET: /{mount_point}/backup/{name}. Produces: 200 application/json
:param name: Name of the key.
:type name: str | unicode
:param mount_point: The "path" the method/backend was mounted on.
:type mount_point: str | unicode
:return: The JSON response of the request.
:rtype: dict
"""
api_path = utils.format_url(
"/v1/{mount_point}/backup/{name}",
mount_point=mount_point,
name=name,
)
return self._adapter.get(
url=api_path,
)
def restore_key(
self, backup, name=None, force=None, mount_point=DEFAULT_MOUNT_POINT
):
"""Restore the backup as a named key.
This will restore the key configurations and all the versions of the named key along with HMAC keys. The input
to this endpoint should be the output of /backup endpoint. For safety, by default the backend will refuse to
restore to an existing key. If you want to reuse a key name, it is recommended you delete the key before
restoring. It is a good idea to attempt restoring to a different key name first to verify that the operation
successfully completes.
Supported methods:
POST: /{mount_point}/restore(/name). Produces: 204 (empty body)
:param backup: Backed up key data to be restored. This should be the output from the /backup endpoint.
:type backup: str | unicode
:param name: If set, this will be the name of the restored key.
:type name: str | unicode
:param force: If set, force the restore to proceed even if a key by this name already exists.
:type force: bool
:param mount_point: The "path" the method/backend was mounted on.
:type mount_point: str | unicode
:return: The response of the request.
:rtype: requests.Response
"""
params = {
"backup": backup,
}
params.update(
utils.remove_nones(
{
"force": force,
}
)
)
api_path = utils.format_url(
"/v1/{mount_point}/restore", mount_point=mount_point
)
if name is not None:
api_path = self._adapter.urljoin(api_path, name)
return self._adapter.post(
url=api_path,
json=params,
)
def trim_key(self, name, min_version, mount_point=DEFAULT_MOUNT_POINT):
"""Trims older key versions setting a minimum version for the keyring.
Once trimmed, previous versions of the key cannot be recovered.
Supported methods:
POST: /{mount_point}/keys/{name}/trim. Produces: 200 application/json
:param name: Specifies the name of the key to be trimmed.
:type name: str | unicode
:param min_version: The minimum version for the key ring. All versions before this version will be permanently
deleted. This value can at most be equal to the lesser of min_decryption_version and min_encryption_version.
This is not allowed to be set when either min_encryption_version or min_decryption_version is set to zero.
:type min_version: int
:param mount_point: The "path" the method/backend was mounted on.
:type mount_point: str | unicode
:return: The response of the request.
:rtype: dict
"""
params = {
"min_available_version": min_version,
}
api_path = utils.format_url(
"/v1/{mount_point}/keys/{name}/trim",
mount_point=mount_point,
name=name,
)
return self._adapter.post(
url=api_path,
json=params,
)
|