├── .github └── workflows │ └── build-lint.yml ├── .gitignore ├── LICENSE ├── README.md ├── auth.go ├── bin └── golangci-lint ├── client.go ├── dynamic_secrets.go ├── folders.go ├── go.mod ├── go.sum ├── kms.go ├── models.go ├── packages ├── api │ ├── auth │ │ ├── aws_iam_auth_login.go │ │ ├── azure_auth_login.go │ │ ├── gcp_id_token_auth_login.go │ │ ├── jwt_auth_login.go │ │ ├── kubernetes_auth_login.go │ │ ├── models.go │ │ ├── oidc_auth_login.go │ │ ├── renew_access_token.go │ │ ├── revoke_access_token.go │ │ └── universal_auth_login.go │ ├── dynamic_secrets │ │ ├── create_lease.go │ │ ├── delete_lease.go │ │ ├── get_lease_by_id.go │ │ ├── get_secret_by_name.go │ │ ├── list_lease.go │ │ ├── list_secrets.go │ │ ├── models.go │ │ └── renew_lease.go │ ├── folders │ │ ├── create_folder.go │ │ ├── delete_folder.go │ │ ├── list_folders.go │ │ ├── models.go │ │ └── update_folder.go │ ├── kms │ │ ├── create_key.go │ │ ├── decrypt_data.go │ │ ├── delete_key.go │ │ ├── encrypt_data.go │ │ ├── get_key_by_name.go │ │ ├── get_public_key.go │ │ ├── get_signing_algorithms.go │ │ ├── models.go │ │ ├── sign_data.go │ │ └── verify_data.go │ ├── secrets │ │ ├── bulk_create_secrets.go │ │ ├── create_secret.go │ │ ├── delete_secret.go │ │ ├── list_secrets.go │ │ ├── models.go │ │ ├── retrieve_secret.go │ │ └── update_secret.go │ └── ssh │ │ ├── add_ssh_host.go │ │ ├── get_ssh_host_host_ca_pk.go │ │ ├── get_ssh_host_user_ca_pk.go │ │ ├── get_ssh_hosts.go │ │ ├── issue_ssh_creds.go │ │ ├── issue_ssh_host_host_cert.go │ │ ├── issue_ssh_host_user_cert.go │ │ ├── models.go │ │ └── sign_ssh_public_key.go ├── errors │ ├── api.go │ └── request.go ├── models │ ├── auth.go │ ├── dynamic_secrets.go │ ├── folders.go │ └── secrets.go └── util │ ├── auth.go │ ├── constants.go │ └── helper.go ├── resources └── logo.svg ├── secrets.go ├── ssh.go └── test ├── aws_auth_test.go ├── kubernetes_auth_test.go ├── secrets_batch_create_test.go ├── ssh_test.go └── universal_auth_test.go /.github/workflows/build-lint.yml: -------------------------------------------------------------------------------- 1 | name: Build and Lint 2 | 3 | # Basic concurrency per branch 4 | concurrency: 5 | group: ${{ github.workflow }}-${{ github.ref }} 6 | cancel-in-progress: true 7 | 8 | on: 9 | pull_request: 10 | types: [opened, synchronize] 11 | 12 | jobs: 13 | build: 14 | name: Build 15 | runs-on: ubuntu-latest 16 | timeout-minutes: 5 17 | steps: 18 | - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 19 | - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 20 | with: 21 | go-version-file: "go.mod" 22 | cache: false 23 | - run: go mod download 24 | - run: go build -v . 25 | - name: Run linters 26 | uses: golangci/golangci-lint-action@5f1fec7010f6ae3b84ea4f7b2129beb8639b564f # v3.5.0 27 | with: 28 | version: latest 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # If you prefer the allow list template instead of the deny list, see community template: 2 | # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore 3 | # 4 | # Binaries for programs and plugins 5 | *.exe 6 | *.exe~ 7 | *.dll 8 | *.so 9 | *.dylib 10 | 11 | # Test binary, built with `go test -c` 12 | *.test 13 | 14 | # Output of the go coverage tool, specifically when used with LiteIDE 15 | *.out 16 | 17 | # Dependency directories (remove the comment below to include it) 18 | # vendor/ 19 | 20 | # Go workspace file 21 | go.work 22 | go.work.sum 23 | .DS_Store 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2024, Infisical Inc 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | infisical 3 |

4 |

5 |

Infisical Go SDK 6 |

7 |

8 | Slack | 9 | Infisical Cloud | 10 | Self-Hosting | 11 | SDK Docs | 12 | Website 13 |

14 | 15 |

16 | 17 | Infisical is released under the MIT license. 18 | 19 | 20 | PRs welcome! 21 | 22 | 23 | git commit activity 24 | 25 | 26 | Slack community channel 27 | 28 | 29 | Infisical Twitter 30 | 31 |

32 | 33 | ## Introduction 34 | 35 | **[Infisical](https://infisical.com)** is the open source secret management platform that teams use to centralize their secrets like API keys, database credentials, and configurations. 36 | 37 | The Infisical Go SDK provides a robust and efficient way for Go developers to integrate Infisical's secret management capabilities into their applications. With our SDK, you can seamlessly retrieve, update, delete, and manage your application's secrets. The SDK offers a simple API, making it easy to integrate Infisical's core features into your Go projects with minimal effort. Whether you are building microservices, cloud-native applications, or any other Go-based systems. 38 | 39 | For detailed documentation on how to get started with the Infisical Go SDK, check out our [SDK Docs](https://infisical.com/docs/sdks/languages/go). 40 | 41 | 42 | ## Security 43 | 44 | Please do not file GitHub issues or post on our public forum for security vulnerabilities, as they are public! 45 | 46 | Infisical takes security issues very seriously. If you have any concerns about Infisical or believe you have uncovered a vulnerability, please get in touch via the e-mail address security@infisical.com. In the message, try to provide a description of the issue and ideally a way of reproducing it. The security team will get back to you as soon as possible. 47 | 48 | Note that this security address should be used only for undisclosed vulnerabilities. Please report any security problems to us before disclosing it publicly. 49 | 50 | 51 | ## Contributing 52 | 53 | Whether it's big or small, we love contributions. Check out our guide to see how to [get started](https://infisical.com/docs/contributing/getting-started). 54 | 55 | Not sure where to get started? Join our Slack, and ask us any questions there. 56 | -------------------------------------------------------------------------------- /auth.go: -------------------------------------------------------------------------------- 1 | package infisical 2 | 3 | import ( 4 | "context" 5 | "crypto/sha256" 6 | "encoding/base64" 7 | "encoding/json" 8 | "errors" 9 | "fmt" 10 | "net/http" 11 | "os" 12 | "strings" 13 | "time" 14 | 15 | api "github.com/infisical/go-sdk/packages/api/auth" 16 | "github.com/infisical/go-sdk/packages/models" 17 | "github.com/infisical/go-sdk/packages/util" 18 | 19 | v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4" 20 | ) 21 | 22 | type KubernetesAuthLoginOptions struct { 23 | IdentityID string 24 | ServiceAccountTokenPath string 25 | } 26 | 27 | // func epochTime() time.Time { return time.Unix(0, 0) } 28 | 29 | type AuthInterface interface { 30 | SetAccessToken(accessToken string) 31 | GetAccessToken() string 32 | UniversalAuthLogin(clientID string, clientSecret string) (credential MachineIdentityCredential, err error) 33 | JwtAuthLogin(identityID string, jwt string) (credential MachineIdentityCredential, err error) 34 | KubernetesAuthLogin(identityID string, serviceAccountTokenPath string) (credential MachineIdentityCredential, err error) 35 | KubernetesRawServiceAccountTokenLogin(identityID string, serviceAccountToken string) (credential MachineIdentityCredential, err error) 36 | AzureAuthLogin(identityID string, resource string) (credential MachineIdentityCredential, err error) 37 | GcpIdTokenAuthLogin(identityID string) (credential MachineIdentityCredential, err error) 38 | GcpIamAuthLogin(identityID string, serviceAccountKeyFilePath string) (credential MachineIdentityCredential, err error) 39 | AwsIamAuthLogin(identityId string) (credential MachineIdentityCredential, err error) 40 | OidcAuthLogin(identityId string, jwt string) (credential MachineIdentityCredential, err error) 41 | RevokeAccessToken() error 42 | } 43 | 44 | type Auth struct { 45 | client *InfisicalClient 46 | } 47 | 48 | func (a *Auth) SetAccessToken(accessToken string) { 49 | a.client.setPlainAccessToken(accessToken) 50 | } 51 | 52 | func (a *Auth) GetAccessToken() string { 53 | // case: user has set an access token manually, so we get it directly from the credential 54 | if a.client.authMethod == util.ACCESS_TOKEN { 55 | if parsedCreds, ok := a.client.credential.(models.AccessTokenCredential); ok { 56 | return parsedCreds.AccessToken 57 | } 58 | return "" 59 | } 60 | return a.client.tokenDetails.AccessToken 61 | } 62 | 63 | func (a *Auth) RevokeAccessToken() error { 64 | if a.client.tokenDetails.AccessToken == "" { 65 | return errors.New("sdk client is not authenticated, cannot revoke access token") 66 | } 67 | 68 | _, err := api.CallRevokeAccessToken(a.client.httpClient, api.RevokeAccessTokenRequest{ 69 | AccessToken: a.client.tokenDetails.AccessToken, 70 | }) 71 | 72 | if err != nil { 73 | return err 74 | } 75 | a.client.clearAccessToken() 76 | 77 | return nil 78 | } 79 | func (a *Auth) UniversalAuthLogin(clientID string, clientSecret string) (credential MachineIdentityCredential, err error) { 80 | 81 | if clientID == "" { 82 | clientID = os.Getenv(util.INFISICAL_UNIVERSAL_AUTH_CLIENT_ID_ENV_NAME) 83 | } 84 | if clientSecret == "" { 85 | clientSecret = os.Getenv(util.INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET_ENV_NAME) 86 | } 87 | 88 | credential, err = api.CallUniversalAuthLogin(a.client.httpClient, api.UniversalAuthLoginRequest{ 89 | ClientID: clientID, 90 | ClientSecret: clientSecret, 91 | }) 92 | 93 | if err != nil { 94 | return MachineIdentityCredential{}, err 95 | } 96 | 97 | a.client.setAccessToken( 98 | credential, 99 | models.UniversalAuthCredential{ClientID: clientID, ClientSecret: clientSecret}, 100 | util.UNIVERSAL_AUTH, 101 | ) 102 | return credential, nil 103 | 104 | } 105 | 106 | func (a *Auth) KubernetesAuthLogin(identityID string, serviceAccountTokenPath string) (credential MachineIdentityCredential, err error) { 107 | 108 | if serviceAccountTokenPath == "" { 109 | serviceAccountTokenPath = os.Getenv(util.DEFAULT_KUBERNETES_SERVICE_ACCOUNT_TOKEN_PATH) 110 | } 111 | if identityID == "" { 112 | identityID = os.Getenv(util.INFISICAL_KUBERNETES_IDENTITY_ID_ENV_NAME) 113 | } 114 | 115 | serviceAccountToken, serviceAccountTokenErr := util.GetKubernetesServiceAccountToken(serviceAccountTokenPath) 116 | 117 | if serviceAccountTokenErr != nil { 118 | return MachineIdentityCredential{}, serviceAccountTokenErr 119 | } 120 | 121 | credential, err = api.CallKubernetesAuthLogin(a.client.httpClient, api.KubernetesAuthLoginRequest{ 122 | IdentityID: identityID, 123 | JWT: serviceAccountToken, 124 | }) 125 | 126 | if err != nil { 127 | return MachineIdentityCredential{}, err 128 | } 129 | 130 | a.client.setAccessToken( 131 | credential, 132 | models.KubernetesCredential{IdentityID: identityID, ServiceAccountToken: serviceAccountToken}, 133 | util.KUBERNETES, 134 | ) 135 | 136 | return credential, nil 137 | 138 | } 139 | 140 | func (a *Auth) KubernetesRawServiceAccountTokenLogin(identityID string, serviceAccountToken string) (credential MachineIdentityCredential, err error) { 141 | 142 | if identityID == "" { 143 | identityID = os.Getenv(util.INFISICAL_KUBERNETES_IDENTITY_ID_ENV_NAME) 144 | } 145 | 146 | credential, err = api.CallKubernetesAuthLogin(a.client.httpClient, api.KubernetesAuthLoginRequest{ 147 | IdentityID: identityID, 148 | JWT: serviceAccountToken, 149 | }) 150 | 151 | if err != nil { 152 | return MachineIdentityCredential{}, err 153 | } 154 | 155 | a.client.setAccessToken( 156 | credential, 157 | models.KubernetesCredential{IdentityID: identityID, ServiceAccountToken: serviceAccountToken}, 158 | util.KUBERNETES, 159 | ) 160 | return credential, nil 161 | } 162 | 163 | func (a *Auth) AzureAuthLogin(identityID string, resource string) (credential MachineIdentityCredential, err error) { 164 | if identityID == "" { 165 | identityID = os.Getenv(util.INFISICAL_AZURE_AUTH_IDENTITY_ID_ENV_NAME) 166 | } 167 | 168 | jwt, jwtError := util.GetAzureMetadataToken(a.client.httpClient, resource) 169 | 170 | if jwtError != nil { 171 | return MachineIdentityCredential{}, jwtError 172 | } 173 | 174 | credential, err = api.CallAzureAuthLogin(a.client.httpClient, api.AzureAuthLoginRequest{ 175 | IdentityID: identityID, 176 | JWT: jwt, 177 | }) 178 | 179 | if err != nil { 180 | return MachineIdentityCredential{}, err 181 | } 182 | 183 | a.client.setAccessToken( 184 | credential, 185 | models.AzureCredential{IdentityID: identityID, Resource: resource}, 186 | util.AZURE, 187 | ) 188 | return credential, nil 189 | } 190 | 191 | func (a *Auth) GcpIdTokenAuthLogin(identityID string) (credential MachineIdentityCredential, err error) { 192 | if identityID == "" { 193 | identityID = os.Getenv(util.INFISICAL_GCP_AUTH_IDENTITY_ID_ENV_NAME) 194 | } 195 | 196 | jwt, jwtError := util.GetGCPMetadataToken(a.client.httpClient, identityID) 197 | 198 | if jwtError != nil { 199 | return MachineIdentityCredential{}, jwtError 200 | } 201 | 202 | credential, err = api.CallGCPAuthLogin(a.client.httpClient, api.GCPAuthLoginRequest{ 203 | IdentityID: identityID, 204 | JWT: jwt, 205 | }) 206 | 207 | if err != nil { 208 | return MachineIdentityCredential{}, err 209 | } 210 | 211 | a.client.setAccessToken( 212 | credential, 213 | models.GCPIDTokenCredential{IdentityID: identityID}, 214 | util.GCP_ID_TOKEN, 215 | ) 216 | return credential, nil 217 | } 218 | 219 | func (a *Auth) GcpIamAuthLogin(identityID string, serviceAccountKeyFilePath string) (credential MachineIdentityCredential, err error) { 220 | if identityID == "" { 221 | identityID = os.Getenv(util.INFISICAL_GCP_AUTH_IDENTITY_ID_ENV_NAME) 222 | } 223 | if serviceAccountKeyFilePath == "" { 224 | serviceAccountKeyFilePath = os.Getenv(util.INFISICAL_GCP_IAM_SERVICE_ACCOUNT_KEY_FILE_PATH_ENV_NAME) 225 | } 226 | 227 | jwt, jwtError := util.GetGCPIamServiceAccountToken(identityID, serviceAccountKeyFilePath) 228 | 229 | if jwtError != nil { 230 | return MachineIdentityCredential{}, jwtError 231 | } 232 | 233 | credential, err = api.CallGCPAuthLogin(a.client.httpClient, api.GCPAuthLoginRequest{ 234 | IdentityID: identityID, 235 | JWT: jwt, 236 | }) 237 | 238 | if err != nil { 239 | return MachineIdentityCredential{}, err 240 | } 241 | 242 | a.client.setAccessToken( 243 | credential, 244 | models.GCPIAMCredential{IdentityID: identityID, ServiceAccountKeyFilePath: serviceAccountKeyFilePath}, 245 | util.GCP_IAM, 246 | ) 247 | return credential, nil 248 | } 249 | 250 | func (a *Auth) AwsIamAuthLogin(identityId string) (credential MachineIdentityCredential, err error) { 251 | 252 | if identityId == "" { 253 | identityId = os.Getenv(util.INFISICAL_AWS_IAM_AUTH_IDENTITY_ID_ENV_NAME) 254 | } 255 | 256 | awsCredentials, awsRegion, err := util.RetrieveAwsCredentials() 257 | if err != nil { 258 | return MachineIdentityCredential{}, err 259 | } 260 | 261 | // Prepare request for signing 262 | iamRequestURL := fmt.Sprintf("https://sts.%s.amazonaws.com/", awsRegion) 263 | iamRequestBody := "Action=GetCallerIdentity&Version=2011-06-15" 264 | 265 | req, err := http.NewRequest(http.MethodPost, iamRequestURL, strings.NewReader(iamRequestBody)) 266 | if err != nil { 267 | return MachineIdentityCredential{}, fmt.Errorf("error creating HTTP request: %v", err) 268 | } 269 | 270 | currentTime := time.Now().UTC() 271 | req.Header.Add("X-Amz-Date", currentTime.Format("20060102T150405Z")) 272 | 273 | hashGenerator := sha256.New() 274 | hashGenerator.Write([]byte(iamRequestBody)) 275 | payloadHash := fmt.Sprintf("%x", hashGenerator.Sum(nil)) 276 | 277 | signer := v4.NewSigner() 278 | err = signer.SignHTTP(context.TODO(), awsCredentials, req, payloadHash, "sts", awsRegion, time.Now()) 279 | 280 | if err != nil { 281 | return MachineIdentityCredential{}, fmt.Errorf("error signing request: %v", err) 282 | } 283 | 284 | var realHeaders map[string]string = make(map[string]string) 285 | for name, values := range req.Header { 286 | if strings.ToLower(name) == "content-length" { 287 | continue 288 | } 289 | realHeaders[name] = values[0] 290 | } 291 | realHeaders["Host"] = fmt.Sprintf("sts.%s.amazonaws.com", awsRegion) 292 | realHeaders["Content-Type"] = "application/x-www-form-urlencoded; charset=utf-8" 293 | realHeaders["Content-Length"] = fmt.Sprintf("%d", len(iamRequestBody)) 294 | 295 | // convert the headers to a json marshalled string 296 | jsonStringHeaders, err := json.Marshal(realHeaders) 297 | 298 | if err != nil { 299 | return MachineIdentityCredential{}, fmt.Errorf("error marshalling headers: %v", err) 300 | } 301 | 302 | credential, tokenErr := api.CallAWSIamAuthLogin(a.client.httpClient, api.AwsIamAuthLoginRequest{ 303 | HTTPRequestMethod: req.Method, 304 | // Encoding is intended, we decode it on severside, and I know everything happening on the server is being done correctly. So it's something broken in this code somewhere. 305 | IamRequestBody: base64.StdEncoding.EncodeToString([]byte(iamRequestBody)), 306 | IamRequestHeaders: base64.StdEncoding.EncodeToString(jsonStringHeaders), 307 | IdentityId: identityId, 308 | }) 309 | 310 | if tokenErr != nil { 311 | return MachineIdentityCredential{}, tokenErr 312 | } 313 | 314 | a.client.setAccessToken( 315 | credential, 316 | models.AWSIAMCredential{IdentityID: identityId}, 317 | util.AWS_IAM, 318 | ) 319 | return credential, nil 320 | } 321 | 322 | func (a *Auth) OidcAuthLogin(identityId string, jwt string) (credential MachineIdentityCredential, err error) { 323 | if identityId == "" { 324 | identityId = os.Getenv(util.INFISICAL_OIDC_AUTH_IDENTITY_ID_ENV_NAME) 325 | } 326 | 327 | credential, err = api.CallOidcAuthLogin(a.client.httpClient, api.OidcAuthLoginRequest{ 328 | IdentityID: identityId, 329 | JWT: jwt, 330 | }) 331 | 332 | if err != nil { 333 | return MachineIdentityCredential{}, err 334 | } 335 | 336 | a.client.setAccessToken( 337 | credential, 338 | models.OIDCCredential{IdentityID: identityId}, 339 | util.OIDC_AUTH, 340 | ) 341 | return credential, nil 342 | 343 | } 344 | 345 | func (a *Auth) JwtAuthLogin(identityID string, jwt string) (credential MachineIdentityCredential, err error) { 346 | credential, err = api.CallJwtAuthLogin(a.client.httpClient, api.JwtAuthLoginRequest{ 347 | IdentityID: identityID, 348 | JWT: jwt, 349 | }) 350 | 351 | if err != nil { 352 | return MachineIdentityCredential{}, err 353 | } 354 | 355 | a.client.setAccessToken( 356 | credential, 357 | models.JWTCredential{IdentityID: identityID, JWT: jwt}, 358 | util.JWT_AUTH, 359 | ) 360 | return credential, nil 361 | } 362 | 363 | func NewAuth(client *InfisicalClient) AuthInterface { 364 | return &Auth{client: client} 365 | } 366 | -------------------------------------------------------------------------------- /bin/golangci-lint: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Infisical/go-sdk/b0c7741ec9fa28c858a8b3a9702fd17933c0a713/bin/golangci-lint -------------------------------------------------------------------------------- /client.go: -------------------------------------------------------------------------------- 1 | package infisical 2 | 3 | import ( 4 | "context" 5 | "crypto/tls" 6 | "crypto/x509" 7 | "errors" 8 | "fmt" 9 | "math" 10 | "math/rand" 11 | "net" 12 | "reflect" 13 | "strconv" 14 | "strings" 15 | "sync" 16 | "time" 17 | 18 | "github.com/go-resty/resty/v2" 19 | "github.com/hashicorp/golang-lru/v2/expirable" 20 | api "github.com/infisical/go-sdk/packages/api/auth" 21 | "github.com/infisical/go-sdk/packages/models" 22 | "github.com/infisical/go-sdk/packages/util" 23 | ) 24 | 25 | type InfisicalClient struct { 26 | authMethod util.AuthMethod 27 | credential interface{} 28 | tokenDetails MachineIdentityCredential 29 | lastFetchedTime time.Time 30 | firstFetchedTime time.Time 31 | 32 | mu sync.RWMutex 33 | 34 | cache *expirable.LRU[string, interface{}] 35 | 36 | httpClient *resty.Client 37 | config Config 38 | 39 | secrets SecretsInterface 40 | folders FoldersInterface 41 | auth AuthInterface 42 | dynamicSecrets DynamicSecretsInterface 43 | kms KmsInterface 44 | ssh SshInterface 45 | } 46 | 47 | type InfisicalClientInterface interface { 48 | UpdateConfiguration(config Config) 49 | Secrets() SecretsInterface 50 | Folders() FoldersInterface 51 | Auth() AuthInterface 52 | DynamicSecrets() DynamicSecretsInterface 53 | Kms() KmsInterface 54 | Ssh() SshInterface 55 | } 56 | 57 | type Config struct { 58 | SiteUrl string `default:"https://app.infisical.com"` 59 | CaCertificate string 60 | UserAgent string `default:"infisical-go-sdk"` // User-Agent header to be used on requests sent by the SDK. Defaults to `infisical-go-sdk`. Do not modify this unless you have a reason to do so. 61 | AutoTokenRefresh bool `default:"true"` // Wether or not to automatically refresh the auth token after using one of the .Auth() methods. Defaults to `true`. 62 | SilentMode bool `default:"false"` // If enabled, the SDK will not print any warnings to the console. 63 | CacheExpiryInSeconds int // Defines how long certain API responses should be cached in memory, in seconds. When set to a positive value, responses from specific fetch API requests (like secret fetching) will be cached for this duration. Set to 0 to disable caching. Defaults to 0. 64 | CustomHeaders map[string]string 65 | } 66 | 67 | func setDefaults(cfg *Config) { 68 | t := reflect.TypeOf(*cfg) // we need to dereference the pointer to get the struct type 69 | v := reflect.ValueOf(cfg).Elem() 70 | 71 | for i := 0; i < t.NumField(); i++ { 72 | field := t.Field(i) 73 | defaultVal := field.Tag.Get("default") 74 | if defaultVal == "" { 75 | continue 76 | } 77 | 78 | switch field.Type.Kind() { 79 | case reflect.Int: 80 | if v.Field(i).Int() == 0 { 81 | val, _ := strconv.Atoi(defaultVal) 82 | v.Field(i).SetInt(int64(val)) 83 | } 84 | case reflect.String: 85 | if v.Field(i).String() == "" { 86 | v.Field(i).SetString(defaultVal) 87 | } 88 | case reflect.Bool: 89 | if !v.Field(i).Bool() { 90 | val, _ := strconv.ParseBool(defaultVal) 91 | v.Field(i).SetBool(val) 92 | } 93 | } 94 | } 95 | } 96 | 97 | func (c *InfisicalClient) setAccessToken(tokenDetails MachineIdentityCredential, credential interface{}, authMethod util.AuthMethod) { 98 | c.mu.Lock() 99 | defer c.mu.Unlock() 100 | 101 | c.tokenDetails = tokenDetails 102 | c.lastFetchedTime = time.Now() 103 | 104 | if c.authMethod != authMethod || c.firstFetchedTime.IsZero() { 105 | c.firstFetchedTime = time.Now() 106 | c.authMethod = authMethod 107 | } 108 | 109 | c.credential = credential 110 | c.httpClient.SetAuthScheme("Bearer") 111 | c.httpClient.SetAuthToken(c.tokenDetails.AccessToken) 112 | } 113 | 114 | func (c *InfisicalClient) clearAccessToken() { 115 | c.mu.Lock() 116 | defer c.mu.Unlock() 117 | 118 | c.tokenDetails = MachineIdentityCredential{} 119 | c.authMethod = "" 120 | c.httpClient.SetAuthScheme("") 121 | c.httpClient.SetAuthToken("") 122 | } 123 | func (c *InfisicalClient) setPlainAccessToken(accessToken string) { 124 | c.mu.Lock() 125 | defer c.mu.Unlock() 126 | 127 | c.authMethod = util.ACCESS_TOKEN 128 | c.httpClient.SetAuthScheme("Bearer") 129 | c.httpClient.SetAuthToken(accessToken) 130 | 131 | c.credential = models.AccessTokenCredential{AccessToken: accessToken} 132 | } 133 | 134 | func NewInfisicalClient(context context.Context, config Config) InfisicalClientInterface { 135 | client := &InfisicalClient{} 136 | setDefaults(&config) 137 | client.UpdateConfiguration(config) // set httpClient and config 138 | 139 | // add interfaces here 140 | client.secrets = NewSecrets(client) 141 | client.folders = NewFolders(client) 142 | client.auth = NewAuth(client) 143 | client.dynamicSecrets = NewDynamicSecrets(client) 144 | client.kms = NewKms(client) 145 | client.ssh = NewSsh(client) 146 | if config.CacheExpiryInSeconds != 0 { 147 | // hard limit set at 1000 cache items until forced eviction 148 | client.cache = expirable.NewLRU[string, interface{}](1000, nil, time.Second*time.Duration(config.CacheExpiryInSeconds)) 149 | } 150 | 151 | if config.AutoTokenRefresh { 152 | go client.handleTokenLifeCycle(context) 153 | } 154 | 155 | return client 156 | } 157 | 158 | func (c *InfisicalClient) UpdateConfiguration(config Config) { 159 | c.mu.Lock() 160 | defer c.mu.Unlock() 161 | 162 | setDefaults(&config) 163 | config.SiteUrl = util.AppendAPIEndpoint(config.SiteUrl) 164 | c.config = config 165 | 166 | if c.httpClient == nil { 167 | c.httpClient = resty.New(). 168 | SetHeader("User-Agent", config.UserAgent). 169 | SetBaseURL(config.SiteUrl) 170 | 171 | c.httpClient.SetRetryCount(3). 172 | SetRetryWaitTime(1 * time.Second). 173 | SetRetryMaxWaitTime(30 * time.Second). 174 | SetRetryAfter(func(c *resty.Client, r *resty.Response) (time.Duration, error) { 175 | 176 | attempt := r.Request.Attempt + 1 177 | if attempt <= 0 { 178 | attempt = 1 179 | } 180 | waitTime := math.Min(float64(c.RetryWaitTime)*math.Pow(2, float64(attempt-1)), float64(c.RetryMaxWaitTime)) 181 | 182 | // Add jitter of +/-20% 183 | jitterFactor := 0.8 + (rand.Float64() * 0.4) 184 | waitTime = waitTime * jitterFactor 185 | 186 | waitDuration := time.Duration(waitTime) 187 | return waitDuration, nil 188 | }). 189 | AddRetryCondition(func(r *resty.Response, err error) bool { 190 | // don't retry if there's no error or it's a timeout 191 | if err == nil || errors.Is(err, context.DeadlineExceeded) { 192 | return false 193 | } 194 | 195 | errMsg := err.Error() 196 | 197 | networkErrors := []string{ 198 | "connection refused", 199 | "connection reset", 200 | "network", 201 | "connection", 202 | "no such host", 203 | "i/o timeout", 204 | "dial tcp", 205 | "broken pipe", 206 | "wsaetimeout", 207 | "wsaeconnreset", 208 | "econnreset", 209 | "econnrefused", 210 | "ehostunreach", 211 | "enetunreach", 212 | } 213 | 214 | isConditionMet := false 215 | 216 | var netErr net.Error 217 | if errors.As(err, &netErr) { 218 | return true 219 | } 220 | 221 | for _, netErr := range networkErrors { 222 | if strings.Contains(strings.ToLower(errMsg), netErr) { 223 | isConditionMet = true 224 | } 225 | } 226 | 227 | return isConditionMet 228 | 229 | }) 230 | 231 | } else { 232 | c.httpClient. 233 | SetHeader("User-Agent", config.UserAgent). 234 | SetBaseURL(config.SiteUrl) 235 | } 236 | 237 | if len(config.CustomHeaders) > 0 { 238 | c.httpClient.SetHeaders(config.CustomHeaders) 239 | } 240 | 241 | if config.CaCertificate != "" { 242 | caCertPool, err := x509.SystemCertPool() 243 | if err != nil && !config.SilentMode { 244 | util.PrintWarning(fmt.Sprintf("failed to load system root CA pool: %v", err)) 245 | } 246 | 247 | if ok := caCertPool.AppendCertsFromPEM([]byte(config.CaCertificate)); !ok && !config.SilentMode { 248 | util.PrintWarning("failed to append CA certificate") 249 | } 250 | 251 | tlsConfig := &tls.Config{ 252 | RootCAs: caCertPool, 253 | } 254 | 255 | c.httpClient.SetTLSClientConfig(tlsConfig) 256 | } 257 | } 258 | 259 | func (c *InfisicalClient) Secrets() SecretsInterface { 260 | return c.secrets 261 | } 262 | 263 | func (c *InfisicalClient) Folders() FoldersInterface { 264 | return c.folders 265 | } 266 | 267 | func (c *InfisicalClient) Auth() AuthInterface { 268 | return c.auth 269 | } 270 | 271 | func (c *InfisicalClient) DynamicSecrets() DynamicSecretsInterface { 272 | return c.dynamicSecrets 273 | } 274 | 275 | func (c *InfisicalClient) Kms() KmsInterface { 276 | return c.kms 277 | } 278 | 279 | func (c *InfisicalClient) Ssh() SshInterface { 280 | return c.ssh 281 | } 282 | 283 | func (c *InfisicalClient) handleTokenLifeCycle(context context.Context) { 284 | var warningPrinted = false 285 | authStrategies := map[util.AuthMethod]func(cred interface{}) (credential MachineIdentityCredential, err error){ 286 | util.UNIVERSAL_AUTH: func(cred interface{}) (credential MachineIdentityCredential, err error) { 287 | if parsedCreds, ok := cred.(models.UniversalAuthCredential); ok { 288 | return c.auth.UniversalAuthLogin(parsedCreds.ClientID, parsedCreds.ClientSecret) 289 | } 290 | return MachineIdentityCredential{}, fmt.Errorf("failed to parse UniversalAuthCredential") 291 | }, 292 | util.KUBERNETES: func(cred interface{}) (credential MachineIdentityCredential, err error) { 293 | if parsedCreds, ok := cred.(models.KubernetesCredential); ok { 294 | return c.auth.KubernetesRawServiceAccountTokenLogin(parsedCreds.IdentityID, parsedCreds.ServiceAccountToken) 295 | } 296 | return MachineIdentityCredential{}, fmt.Errorf("failed to parse KubernetesAuthCredential") 297 | }, 298 | util.AZURE: func(cred interface{}) (credential MachineIdentityCredential, err error) { 299 | if parsedCreds, ok := cred.(models.AzureCredential); ok { 300 | return c.auth.AzureAuthLogin(parsedCreds.IdentityID, parsedCreds.Resource) 301 | } 302 | return MachineIdentityCredential{}, fmt.Errorf("failed to parse AzureAuthCredential") 303 | }, 304 | util.GCP_ID_TOKEN: func(cred interface{}) (credential MachineIdentityCredential, err error) { 305 | if parsedCreds, ok := cred.(models.GCPIDTokenCredential); ok { 306 | return c.auth.GcpIdTokenAuthLogin(parsedCreds.IdentityID) 307 | } 308 | 309 | return MachineIdentityCredential{}, fmt.Errorf("failed to parse GCPIDTokenCredential") 310 | }, 311 | util.GCP_IAM: func(cred interface{}) (credential MachineIdentityCredential, err error) { 312 | if parsedCreds, ok := cred.(models.GCPIAMCredential); ok { 313 | return c.auth.GcpIamAuthLogin(parsedCreds.IdentityID, parsedCreds.ServiceAccountKeyFilePath) 314 | } 315 | return MachineIdentityCredential{}, fmt.Errorf("failed to parse GCPIAMCredential") 316 | }, 317 | util.AWS_IAM: func(cred interface{}) (credential MachineIdentityCredential, err error) { 318 | if parsedCreds, ok := cred.(models.AWSIAMCredential); ok { 319 | return c.auth.AwsIamAuthLogin(parsedCreds.IdentityID) 320 | } 321 | 322 | return MachineIdentityCredential{}, fmt.Errorf("failed to parse AWSIAMCredential") 323 | }, 324 | util.JWT_AUTH: func(cred interface{}) (credential MachineIdentityCredential, err error) { 325 | if parsedCreds, ok := cred.(models.JWTCredential); ok { 326 | return c.auth.JwtAuthLogin(parsedCreds.IdentityID, parsedCreds.JWT) 327 | } 328 | return MachineIdentityCredential{}, fmt.Errorf("failed to parse JWTCredential") 329 | }, 330 | } 331 | 332 | const RE_AUTHENTICATION_INTERVAL_BUFFER = 2 333 | const RENEWAL_INTERVAL_BUFFER = 5 334 | 335 | for { 336 | select { 337 | case <-context.Done(): 338 | return // The context has been cancelled, clean up and return from the loop to stop the goroutine 339 | default: 340 | { 341 | 342 | c.mu.RLock() 343 | config := c.config 344 | authMethod := c.authMethod 345 | tokenDetails := c.tokenDetails 346 | clientCredential := c.credential 347 | c.mu.RUnlock() 348 | 349 | if config.AutoTokenRefresh && authMethod != "" && authMethod != util.ACCESS_TOKEN { 350 | 351 | if !config.SilentMode && !warningPrinted && tokenDetails.AccessTokenMaxTTL != 0 && tokenDetails.ExpiresIn != 0 { 352 | if tokenDetails.AccessTokenMaxTTL < 60 || tokenDetails.ExpiresIn < 60 { 353 | util.PrintWarning("Machine Identity access token TTL or max TTL is less than 60 seconds. This may cause excessive API calls, and you may be subject to rate-limits.") 354 | } 355 | warningPrinted = true 356 | } 357 | 358 | c.mu.RLock() 359 | 360 | timeNow := time.Now() 361 | timeSinceLastFetchSeconds := timeNow.Sub(c.lastFetchedTime).Seconds() 362 | timeSinceFirstFetchSeconds := timeNow.Sub(c.firstFetchedTime).Seconds() 363 | c.mu.RUnlock() 364 | 365 | if timeSinceFirstFetchSeconds >= float64(tokenDetails.AccessTokenMaxTTL-RE_AUTHENTICATION_INTERVAL_BUFFER) { 366 | newToken, err := authStrategies[c.authMethod](clientCredential) 367 | 368 | if err != nil && !config.SilentMode { 369 | util.PrintWarning(fmt.Sprintf("Failed to re-authenticate: %s\n", err.Error())) 370 | } else { 371 | c.setAccessToken(newToken, c.credential, c.authMethod) 372 | c.mu.Lock() 373 | c.firstFetchedTime = time.Now() 374 | c.mu.Unlock() 375 | } 376 | 377 | } else if timeSinceLastFetchSeconds >= float64(tokenDetails.ExpiresIn-RENEWAL_INTERVAL_BUFFER) { 378 | timeUntilMaxTTL := float64(tokenDetails.AccessTokenMaxTTL) - timeSinceFirstFetchSeconds 379 | 380 | // Case 1: The time until the max TTL is less than the time until the next access token expiry 381 | if timeUntilMaxTTL < float64(tokenDetails.ExpiresIn) { 382 | // If renewing would exceed max TTL, directly re-authenticate 383 | newToken, err := authStrategies[c.authMethod](clientCredential) 384 | if err != nil && !config.SilentMode { 385 | util.PrintWarning(fmt.Sprintf("Failed to re-authenticate: %s\n", err.Error())) 386 | } else { 387 | c.setAccessToken(newToken, c.credential, c.authMethod) 388 | c.mu.Lock() 389 | c.firstFetchedTime = time.Now() 390 | c.mu.Unlock() 391 | } 392 | // Case 2: The time until the max TTL is greater than the time until the next access token expiry 393 | } else { 394 | renewedCredential, err := api.CallRenewAccessToken(c.httpClient, api.RenewAccessTokenRequest{AccessToken: tokenDetails.AccessToken}) 395 | 396 | if err != nil { 397 | if !config.SilentMode { 398 | util.PrintWarning(fmt.Sprintf("Failed to renew access token: %s\n\nAttempting to re-authenticate.", err.Error())) 399 | } 400 | 401 | newToken, err := authStrategies[c.authMethod](clientCredential) 402 | if err != nil && !config.SilentMode { 403 | util.PrintWarning(fmt.Sprintf("Failed to re-authenticate: %s\n", err.Error())) 404 | } else { 405 | c.setAccessToken(newToken, c.credential, c.authMethod) 406 | c.mu.Lock() 407 | c.firstFetchedTime = time.Now() 408 | c.mu.Unlock() 409 | } 410 | } else { 411 | c.setAccessToken(renewedCredential, clientCredential, authMethod) 412 | } 413 | } 414 | } 415 | 416 | c.mu.RLock() 417 | nextAccessTokenExpiresInTime := c.lastFetchedTime.Add(time.Duration(tokenDetails.ExpiresIn*int64(time.Second)) - (5 * time.Second)) 418 | accessTokenMaxTTLExpiresInTime := c.firstFetchedTime.Add(time.Duration(tokenDetails.AccessTokenMaxTTL*int64(time.Second)) - (5 * time.Second)) 419 | expiresIn := time.Duration(c.tokenDetails.ExpiresIn * int64(time.Second)) 420 | c.mu.RUnlock() 421 | 422 | if nextAccessTokenExpiresInTime.After(accessTokenMaxTTLExpiresInTime) { 423 | // Calculate the sleep time 424 | sleepTime := expiresIn - nextAccessTokenExpiresInTime.Sub(accessTokenMaxTTLExpiresInTime) 425 | 426 | // Ensure we sleep for at least 1 second 427 | if sleepTime < 1*time.Second { 428 | sleepTime = time.Second * 1 429 | } 430 | 431 | if err := util.SleepWithContext(context, sleepTime); err != nil && (err == util.ErrContextCanceled || errors.Is(err, util.ErrContextDeadlineExceeded)) { 432 | return 433 | } 434 | 435 | } else { 436 | sleepTime := expiresIn - (5 * time.Second) 437 | 438 | if sleepTime < time.Second { 439 | sleepTime = time.Millisecond * 500 440 | } 441 | 442 | if err := util.SleepWithContext(context, sleepTime); err != nil && (err == util.ErrContextCanceled || errors.Is(err, util.ErrContextDeadlineExceeded)) { 443 | return 444 | } 445 | } 446 | } else { 447 | if err := util.SleepWithContext(context, 1*time.Second); err != nil && (err == util.ErrContextCanceled || errors.Is(err, util.ErrContextDeadlineExceeded)) { 448 | return 449 | } 450 | } 451 | } 452 | } 453 | } 454 | } 455 | -------------------------------------------------------------------------------- /dynamic_secrets.go: -------------------------------------------------------------------------------- 1 | package infisical 2 | 3 | import ( 4 | api "github.com/infisical/go-sdk/packages/api/dynamic_secrets" 5 | "github.com/infisical/go-sdk/packages/models" 6 | ) 7 | 8 | type ListDynamicSecretLeasesOptions = api.ListDynamicSecretLeaseV1Request 9 | type CreateDynamicSecretLeaseOptions = api.CreateDynamicSecretLeaseV1Request 10 | type DeleteDynamicSecretLeaseOptions = api.DeleteDynamicSecretLeaseV1Request 11 | type GetDynamicSecretLeaseByIdOptions = api.GetDynamicSecretLeaseByIdV1Request 12 | type RenewDynamicSecretLeaseOptions = api.RenewDynamicSecretLeaseV1Request 13 | type ListDynamicSecretsRootCredentialsOptions = api.ListDynamicSecretsV1Request 14 | type GetDynamicSecretRootCredentialByNameOptions = api.GetDynamicSecretByNameV1Request 15 | 16 | type DynamicSecretsInterface interface { 17 | List(options ListDynamicSecretsRootCredentialsOptions) ([]models.DynamicSecret, error) 18 | GetByName(options GetDynamicSecretRootCredentialByNameOptions) (models.DynamicSecret, error) 19 | Leases() DynamicSecretLeaseInterface 20 | } 21 | 22 | type DynamicSecretLeaseInterface interface { 23 | List(options ListDynamicSecretLeasesOptions) ([]models.DynamicSecretLease, error) 24 | Create(options CreateDynamicSecretLeaseOptions) (map[string]any, models.DynamicSecret, models.DynamicSecretLease, error) 25 | GetById(options GetDynamicSecretLeaseByIdOptions) (models.DynamicSecretLeaseWithDynamicSecret, error) 26 | DeleteById(options DeleteDynamicSecretLeaseOptions) (models.DynamicSecretLease, error) 27 | RenewById(options RenewDynamicSecretLeaseOptions) (models.DynamicSecretLease, error) 28 | } 29 | 30 | type DynamicSecrets struct { 31 | client *InfisicalClient 32 | leases DynamicSecretLeaseInterface 33 | } 34 | 35 | func (f *DynamicSecrets) List(options ListDynamicSecretsRootCredentialsOptions) ([]models.DynamicSecret, error) { 36 | res, err := api.CallListDynamicSecretsV1(f.client.httpClient, options) 37 | 38 | if err != nil { 39 | return nil, err 40 | } 41 | 42 | return res.DynamicSecrets, nil 43 | } 44 | 45 | func (f *DynamicSecrets) GetByName(options GetDynamicSecretRootCredentialByNameOptions) (models.DynamicSecret, error) { 46 | res, err := api.CallGetDynamicSecretByNameV1(f.client.httpClient, options) 47 | 48 | if err != nil { 49 | return models.DynamicSecret{}, err 50 | } 51 | 52 | return res.DynamicSecret, nil 53 | } 54 | 55 | func (f *DynamicSecrets) Leases() DynamicSecretLeaseInterface { 56 | return f.leases 57 | } 58 | 59 | type DynamicSecretLeases struct { 60 | client *InfisicalClient 61 | } 62 | 63 | func (f *DynamicSecretLeases) List(options ListDynamicSecretLeasesOptions) ([]models.DynamicSecretLease, error) { 64 | res, err := api.CallListDynamicSecretLeaseV1(f.client.httpClient, options) 65 | 66 | if err != nil { 67 | return nil, err 68 | } 69 | 70 | return res.Leases, nil 71 | } 72 | 73 | func (f *DynamicSecretLeases) Create(options CreateDynamicSecretLeaseOptions) (map[string]any, models.DynamicSecret, models.DynamicSecretLease, error) { 74 | res, err := api.CallCreateDynamicSecretLeaseV1(f.client.httpClient, options) 75 | 76 | if err != nil { 77 | return nil, models.DynamicSecret{}, models.DynamicSecretLease{}, err 78 | } 79 | 80 | return res.Data, res.DynamicSecret, res.Lease, nil 81 | } 82 | 83 | func (f *DynamicSecretLeases) GetById(options GetDynamicSecretLeaseByIdOptions) (models.DynamicSecretLeaseWithDynamicSecret, error) { 84 | res, err := api.CallGetByDynamicSecretByIdLeaseV1(f.client.httpClient, options) 85 | 86 | if err != nil { 87 | return models.DynamicSecretLeaseWithDynamicSecret{}, err 88 | } 89 | 90 | return res.Lease, nil 91 | } 92 | 93 | func (f *DynamicSecretLeases) DeleteById(options DeleteDynamicSecretLeaseOptions) (models.DynamicSecretLease, error) { 94 | res, err := api.CallDeleteDynamicSecretLeaseV1(f.client.httpClient, options) 95 | 96 | if err != nil { 97 | return models.DynamicSecretLease{}, err 98 | } 99 | 100 | return res.Lease, nil 101 | } 102 | 103 | func (f *DynamicSecretLeases) RenewById(options RenewDynamicSecretLeaseOptions) (models.DynamicSecretLease, error) { 104 | res, err := api.CallRenewDynamicSecretLeaseV1(f.client.httpClient, options) 105 | 106 | if err != nil { 107 | return models.DynamicSecretLease{}, err 108 | } 109 | 110 | return res.Lease, nil 111 | } 112 | 113 | func NewDynamicSecrets(client *InfisicalClient) DynamicSecretsInterface { 114 | return &DynamicSecrets{client: client, leases: &DynamicSecretLeases{client: client}} 115 | } 116 | -------------------------------------------------------------------------------- /folders.go: -------------------------------------------------------------------------------- 1 | package infisical 2 | 3 | import ( 4 | api "github.com/infisical/go-sdk/packages/api/folders" 5 | "github.com/infisical/go-sdk/packages/models" 6 | ) 7 | 8 | type ListFoldersOptions = api.ListFoldersV1Request 9 | type UpdateFolderOptions = api.UpdateFolderV1Request 10 | type CreateFolderOptions = api.CreateFolderV1Request 11 | type DeleteFolderOptions = api.DeleteFolderV1Request 12 | 13 | type FoldersInterface interface { 14 | List(options ListFoldersOptions) ([]models.Folder, error) 15 | Update(options UpdateFolderOptions) (models.Folder, error) 16 | Create(options CreateFolderOptions) (models.Folder, error) 17 | Delete(options DeleteFolderOptions) (models.Folder, error) 18 | } 19 | 20 | type Folders struct { 21 | client *InfisicalClient 22 | } 23 | 24 | func (f *Folders) List(options ListFoldersOptions) ([]models.Folder, error) { 25 | res, err := api.CallListFoldersV1(f.client.httpClient, options) 26 | 27 | if err != nil { 28 | return nil, err 29 | } 30 | 31 | return res.Folders, nil 32 | } 33 | 34 | func (f *Folders) Update(options UpdateFolderOptions) (models.Folder, error) { 35 | res, err := api.CallUpdateFolderV1(f.client.httpClient, options) 36 | 37 | if err != nil { 38 | return models.Folder{}, err 39 | } 40 | 41 | return res.Folder, nil 42 | } 43 | 44 | func (f *Folders) Create(options CreateFolderOptions) (models.Folder, error) { 45 | res, err := api.CallCreateFolderV1(f.client.httpClient, options) 46 | 47 | if err != nil { 48 | return models.Folder{}, err 49 | } 50 | 51 | return res.Folder, nil 52 | } 53 | 54 | func (f *Folders) Delete(options DeleteFolderOptions) (models.Folder, error) { 55 | res, err := api.CallDeleteFolderV1(f.client.httpClient, options) 56 | 57 | if err != nil { 58 | return models.Folder{}, err 59 | } 60 | 61 | return res.Folder, nil 62 | } 63 | 64 | func NewFolders(client *InfisicalClient) FoldersInterface { 65 | return &Folders{client: client} 66 | } 67 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/infisical/go-sdk 2 | 3 | go 1.21 4 | 5 | require ( 6 | cloud.google.com/go/iam v1.1.11 7 | github.com/aws/aws-sdk-go-v2 v1.27.2 8 | github.com/aws/aws-sdk-go-v2/config v1.27.18 9 | github.com/go-resty/resty/v2 v2.13.1 10 | github.com/hashicorp/golang-lru/v2 v2.0.7 11 | google.golang.org/api v0.188.0 12 | ) 13 | 14 | require ( 15 | cloud.google.com/go/auth v0.7.0 // indirect 16 | cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect 17 | cloud.google.com/go/compute/metadata v0.4.0 // indirect 18 | github.com/aws/aws-sdk-go-v2/credentials v1.17.18 // indirect 19 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.5 // indirect 20 | github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.9 // indirect 21 | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.9 // indirect 22 | github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect 23 | github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect 24 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.11 // indirect 25 | github.com/aws/aws-sdk-go-v2/service/sso v1.20.11 // indirect 26 | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5 // indirect 27 | github.com/aws/aws-sdk-go-v2/service/sts v1.28.12 // indirect 28 | github.com/aws/smithy-go v1.20.2 // indirect 29 | github.com/felixge/httpsnoop v1.0.4 // indirect 30 | github.com/go-logr/logr v1.4.1 // indirect 31 | github.com/go-logr/stdr v1.2.2 // indirect 32 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect 33 | github.com/golang/protobuf v1.5.4 // indirect 34 | github.com/google/s2a-go v0.1.7 // indirect 35 | github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect 36 | github.com/googleapis/gax-go/v2 v2.12.5 // indirect 37 | go.opencensus.io v0.24.0 // indirect 38 | go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect 39 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect 40 | go.opentelemetry.io/otel v1.24.0 // indirect 41 | go.opentelemetry.io/otel/metric v1.24.0 // indirect 42 | go.opentelemetry.io/otel/trace v1.24.0 // indirect 43 | golang.org/x/crypto v0.31.0 // indirect 44 | golang.org/x/net v0.33.0 // indirect 45 | golang.org/x/oauth2 v0.21.0 // indirect 46 | golang.org/x/sync v0.10.0 // indirect 47 | golang.org/x/sys v0.28.0 // indirect 48 | golang.org/x/text v0.21.0 // indirect 49 | golang.org/x/time v0.5.0 // indirect 50 | google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect 51 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240708141625-4ad9e859172b // indirect 52 | google.golang.org/grpc v1.64.1 // indirect 53 | google.golang.org/protobuf v1.34.2 // indirect 54 | ) 55 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go/auth v0.7.0 h1:kf/x9B3WTbBUHkC+1VS8wwwli9TzhSt0vSTVBmMR8Ts= 3 | cloud.google.com/go/auth v0.7.0/go.mod h1:D+WqdrpcjmiCgWrXmLLxOVq1GACoE36chW6KXoEvuIw= 4 | cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4= 5 | cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= 6 | cloud.google.com/go/compute/metadata v0.4.0 h1:vHzJCWaM4g8XIcm8kopr3XmDA4Gy/lblD3EhhSux05c= 7 | cloud.google.com/go/compute/metadata v0.4.0/go.mod h1:SIQh1Kkb4ZJ8zJ874fqVkslA29PRXuleyj6vOzlbK7M= 8 | cloud.google.com/go/iam v1.1.11 h1:0mQ8UKSfdHLut6pH9FM3bI55KWR46ketn0PuXleDyxw= 9 | cloud.google.com/go/iam v1.1.11/go.mod h1:biXoiLWYIKntto2joP+62sd9uW5EpkZmKIvfNcTWlnQ= 10 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 11 | github.com/aws/aws-sdk-go-v2 v1.27.2 h1:pLsTXqX93rimAOZG2FIYraDQstZaaGVVN4tNw65v0h8= 12 | github.com/aws/aws-sdk-go-v2 v1.27.2/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM= 13 | github.com/aws/aws-sdk-go-v2/config v1.27.18 h1:wFvAnwOKKe7QAyIxziwSKjmer9JBMH1vzIL6W+fYuKk= 14 | github.com/aws/aws-sdk-go-v2/config v1.27.18/go.mod h1:0xz6cgdX55+kmppvPm2IaKzIXOheGJhAufacPJaXZ7c= 15 | github.com/aws/aws-sdk-go-v2/credentials v1.17.18 h1:D/ALDWqK4JdY3OFgA2thcPO1c9aYTT5STS/CvnkqY1c= 16 | github.com/aws/aws-sdk-go-v2/credentials v1.17.18/go.mod h1:JuitCWq+F5QGUrmMPsk945rop6bB57jdscu+Glozdnc= 17 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.5 h1:dDgptDO9dxeFkXy+tEgVkzSClHZje/6JkPW5aZyEvrQ= 18 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.5/go.mod h1:gjvE2KBUgUQhcv89jqxrIxH9GaKs1JbZzWejj/DaHGA= 19 | github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.9 h1:cy8ahBJuhtM8GTTSyOkfy6WVPV1IE+SS5/wfXUYuulw= 20 | github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.9/go.mod h1:CZBXGLaJnEZI6EVNcPd7a6B5IC5cA/GkRWtu9fp3S6Y= 21 | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.9 h1:A4SYk07ef04+vxZToz9LWvAXl9LW0NClpPpMsi31cz0= 22 | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.9/go.mod h1:5jJcHuwDagxN+ErjQ3PU3ocf6Ylc/p9x+BLO/+X4iXw= 23 | github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU= 24 | github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY= 25 | github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1xUsUr3I8cHps0G+XM3WWU16lP6yG8qu1GAZAs= 26 | github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg= 27 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.11 h1:o4T+fKxA3gTMcluBNZZXE9DNaMkJuUL1O3mffCUjoJo= 28 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.11/go.mod h1:84oZdJ+VjuJKs9v1UTC9NaodRZRseOXCTgku+vQJWR8= 29 | github.com/aws/aws-sdk-go-v2/service/sso v1.20.11 h1:gEYM2GSpr4YNWc6hCd5nod4+d4kd9vWIAWrmGuLdlMw= 30 | github.com/aws/aws-sdk-go-v2/service/sso v1.20.11/go.mod h1:gVvwPdPNYehHSP9Rs7q27U1EU+3Or2ZpXvzAYJNh63w= 31 | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5 h1:iXjh3uaH3vsVcnyZX7MqCoCfcyxIrVE9iOQruRaWPrQ= 32 | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5/go.mod h1:5ZXesEuy/QcO0WUnt+4sDkxhdXRHTu2yG0uCSH8B6os= 33 | github.com/aws/aws-sdk-go-v2/service/sts v1.28.12 h1:M/1u4HBpwLuMtjlxuI2y6HoVLzF5e2mfxHCg7ZVMYmk= 34 | github.com/aws/aws-sdk-go-v2/service/sts v1.28.12/go.mod h1:kcfd+eTdEi/40FIbLq4Hif3XMXnl5b/+t/KTfLt9xIk= 35 | github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q= 36 | github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= 37 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 38 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 39 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 40 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 41 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 42 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 43 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 44 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 45 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 46 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 47 | github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= 48 | github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= 49 | github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= 50 | github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= 51 | github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 52 | github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= 53 | github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= 54 | github.com/go-resty/resty/v2 v2.13.1 h1:x+LHXBI2nMB1vqndymf26quycC4aggYJ7DECYbiz03g= 55 | github.com/go-resty/resty/v2 v2.13.1/go.mod h1:GznXlLxkq6Nh4sU59rPmUw3VtgpO3aS96ORAI6Q7d+0= 56 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 57 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 58 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= 59 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 60 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 61 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 62 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 63 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 64 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 65 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 66 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 67 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 68 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 69 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 70 | github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= 71 | github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= 72 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 73 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 74 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 75 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 76 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 77 | github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 78 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 79 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 80 | github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= 81 | github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= 82 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 83 | github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= 84 | github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= 85 | github.com/googleapis/gax-go/v2 v2.12.5 h1:8gw9KZK8TiVKB6q3zHY3SBzLnrGp6HQjyfYBYGmXdxA= 86 | github.com/googleapis/gax-go/v2 v2.12.5/go.mod h1:BUDKcWo+RaKq5SC9vVYL0wLADa3VcfswbOMMRmB9H3E= 87 | github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= 88 | github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= 89 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 90 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 91 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 92 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 93 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 94 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 95 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 96 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 97 | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 98 | github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= 99 | github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 100 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 101 | go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= 102 | go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= 103 | go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= 104 | go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= 105 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= 106 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= 107 | go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= 108 | go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= 109 | go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= 110 | go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= 111 | go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= 112 | go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= 113 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 114 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 115 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 116 | golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= 117 | golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= 118 | golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= 119 | golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= 120 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 121 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 122 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 123 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 124 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 125 | golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 126 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 127 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 128 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 129 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 130 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 131 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 132 | golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 133 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 134 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 135 | golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 136 | golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= 137 | golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= 138 | golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= 139 | golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= 140 | golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= 141 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 142 | golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= 143 | golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= 144 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 145 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 146 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 147 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 148 | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 149 | golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= 150 | golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 151 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 152 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 153 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 154 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 155 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 156 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 157 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 158 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 159 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 160 | golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 161 | golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 162 | golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 163 | golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= 164 | golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 165 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 166 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 167 | golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= 168 | golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= 169 | golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= 170 | golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= 171 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 172 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 173 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 174 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 175 | golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 176 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 177 | golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 178 | golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= 179 | golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= 180 | golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= 181 | golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= 182 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 183 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 184 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 185 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 186 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 187 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 188 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 189 | golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 190 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 191 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 192 | google.golang.org/api v0.188.0 h1:51y8fJ/b1AaaBRJr4yWm96fPcuxSo0JcegXE3DaHQHw= 193 | google.golang.org/api v0.188.0/go.mod h1:VR0d+2SIiWOYG3r/jdm7adPW9hI2aRv9ETOSCQ9Beag= 194 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 195 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 196 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 197 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 198 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 199 | google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= 200 | google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= 201 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240708141625-4ad9e859172b h1:04+jVzTs2XBnOZcPsLnmrTGqltqJbZQ1Ey26hjYdQQ0= 202 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240708141625-4ad9e859172b/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= 203 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 204 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 205 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 206 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 207 | google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= 208 | google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA= 209 | google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= 210 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 211 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 212 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 213 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 214 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 215 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 216 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 217 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 218 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 219 | google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= 220 | google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= 221 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 222 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 223 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 224 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 225 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 226 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 227 | -------------------------------------------------------------------------------- /kms.go: -------------------------------------------------------------------------------- 1 | package infisical 2 | 3 | import ( 4 | "encoding/base64" 5 | 6 | api "github.com/infisical/go-sdk/packages/api/kms" 7 | ) 8 | 9 | // Options 10 | type KmsEncryptDataOptions = api.KmsEncryptDataV1Request 11 | type KmsDecryptDataOptions = api.KmsDecryptDataV1Request 12 | 13 | type KmsSignDataOptions = api.KmsSignDataV1Request 14 | type KmsVerifyDataOptions = api.KmsVerifyDataV1Request 15 | 16 | type KmsListSigningAlgorithmsOptions = api.KmsListSigningAlgorithmsV1Request 17 | type KmsGetPublicKeyOptions = api.KmsGetPublicKeyV1Request 18 | 19 | type KmsCreateKeyOptions = api.KmsCreateKeyV1Request 20 | type KmsDeleteKeyOptions = api.KmsDeleteKeyV1Request 21 | 22 | type KmsGetKeyByNameOptions = api.KmsGetKeyByNameV1Request 23 | 24 | // Results 25 | type KmsVerifyDataResult = api.KmsVerifyDataV1Response 26 | type KmsSignDataResult = api.KmsSignDataV1Response 27 | 28 | type KmsCreateKeyResult = api.KmsKey 29 | type KmsDeleteKeyResult = api.KmsKey 30 | type KmsGetKeyResult = api.KmsKey 31 | 32 | type KmsKeysInterface interface { 33 | Create(options KmsCreateKeyOptions) (KmsCreateKeyResult, error) 34 | Delete(options KmsDeleteKeyOptions) (KmsDeleteKeyResult, error) 35 | GetByName(options KmsGetKeyByNameOptions) (KmsGetKeyResult, error) 36 | } 37 | 38 | type KmsSigningInterface interface { 39 | SignData(options KmsSignDataOptions) ([]byte, error) 40 | VerifyData(options KmsVerifyDataOptions) (KmsVerifyDataResult, error) 41 | ListSigningAlgorithms(options KmsListSigningAlgorithmsOptions) ([]string, error) 42 | GetPublicKey(options KmsGetPublicKeyOptions) (string, error) 43 | } 44 | 45 | type KmsInterface interface { 46 | EncryptData(options KmsEncryptDataOptions) (string, error) 47 | DecryptData(options KmsDecryptDataOptions) (string, error) 48 | 49 | Keys() KmsKeysInterface 50 | Signing() KmsSigningInterface 51 | } 52 | 53 | type Kms struct { 54 | client *InfisicalClient 55 | keys *KmsKeys 56 | signing *KmsSigning 57 | } 58 | 59 | type KmsKeys struct { 60 | client *InfisicalClient 61 | } 62 | 63 | type KmsSigning struct { 64 | client *InfisicalClient 65 | } 66 | 67 | func (k *KmsKeys) Create(options KmsCreateKeyOptions) (KmsCreateKeyResult, error) { 68 | res, err := api.CallKmsCreateKeyV1(k.client.httpClient, options) 69 | 70 | if err != nil { 71 | return KmsCreateKeyResult{}, err 72 | } 73 | 74 | return res.Key, nil 75 | } 76 | 77 | func (k *KmsKeys) Delete(options KmsDeleteKeyOptions) (KmsDeleteKeyResult, error) { 78 | res, err := api.CallKmsDeleteKeyV1(k.client.httpClient, options) 79 | 80 | if err != nil { 81 | return KmsDeleteKeyResult{}, err 82 | } 83 | 84 | return res.Key, nil 85 | } 86 | 87 | func (k *KmsKeys) GetByName(options KmsGetKeyByNameOptions) (KmsGetKeyResult, error) { 88 | res, err := api.CallKmsGetKeyByNameV1(k.client.httpClient, options) 89 | 90 | if err != nil { 91 | return KmsGetKeyResult{}, err 92 | } 93 | 94 | return res.Key, nil 95 | } 96 | 97 | func (k *KmsSigning) SignData(options KmsSignDataOptions) ([]byte, error) { 98 | res, err := api.CallKmsSignDataV1(k.client.httpClient, options) 99 | 100 | if err != nil { 101 | return nil, err 102 | } 103 | 104 | return base64.StdEncoding.DecodeString(res.Signature) 105 | } 106 | 107 | func (k *KmsSigning) VerifyData(options KmsVerifyDataOptions) (KmsVerifyDataResult, error) { 108 | res, err := api.CallKmsVerifyDataV1(k.client.httpClient, options) 109 | 110 | if err != nil { 111 | return KmsVerifyDataResult{}, err 112 | } 113 | 114 | return res, nil 115 | } 116 | 117 | func (k *KmsSigning) ListSigningAlgorithms(options KmsListSigningAlgorithmsOptions) ([]string, error) { 118 | res, err := api.CallKmsGetSigningAlgorithmsV1(k.client.httpClient, options) 119 | 120 | if err != nil { 121 | return []string{}, err 122 | } 123 | 124 | return res.SigningAlgorithms, nil 125 | } 126 | 127 | func (k *KmsSigning) GetPublicKey(options KmsGetPublicKeyOptions) (string, error) { 128 | res, err := api.CallKmsGetPublicKeyV1(k.client.httpClient, options) 129 | 130 | if err != nil { 131 | return "", err 132 | } 133 | 134 | return res.PublicKey, nil 135 | } 136 | 137 | func (f *Kms) EncryptData(options KmsEncryptDataOptions) (string, error) { 138 | options.Plaintext = base64.StdEncoding.EncodeToString([]byte(options.Plaintext)) 139 | res, err := api.CallKmsEncryptDataV1(f.client.httpClient, options) 140 | 141 | if err != nil { 142 | return "", err 143 | } 144 | 145 | return res.Ciphertext, nil 146 | } 147 | 148 | func (f *Kms) DecryptData(options KmsDecryptDataOptions) (string, error) { 149 | res, err := api.CallKmsDecryptDataV1(f.client.httpClient, options) 150 | 151 | if err != nil { 152 | return "", err 153 | } 154 | 155 | decodedPlaintext, err := base64.StdEncoding.DecodeString(res.Plaintext) 156 | if err != nil { 157 | return "", err 158 | } 159 | 160 | return string(decodedPlaintext), nil 161 | } 162 | 163 | func (f *Kms) Keys() KmsKeysInterface { 164 | return &KmsKeys{client: f.client} 165 | } 166 | 167 | func (f *Kms) Signing() KmsSigningInterface { 168 | return &KmsSigning{client: f.client} 169 | } 170 | 171 | func NewKms(client *InfisicalClient) KmsInterface { 172 | return &Kms{ 173 | client: client, 174 | keys: &KmsKeys{client: client}, 175 | signing: &KmsSigning{client: client}, 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /models.go: -------------------------------------------------------------------------------- 1 | package infisical 2 | 3 | import ( 4 | api "github.com/infisical/go-sdk/packages/api/auth" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | "github.com/infisical/go-sdk/packages/models" 7 | ) 8 | 9 | type MachineIdentityCredential = api.MachineIdentityAuthLoginResponse 10 | 11 | type Secret = models.Secret 12 | type SecretImport = models.SecretImport 13 | 14 | type APIError = errors.APIError 15 | type RequestError = errors.RequestError 16 | -------------------------------------------------------------------------------- /packages/api/auth/aws_iam_auth_login.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | ) 7 | 8 | const callAWSIamAuthLoginOperation = "CallAWSIamAuthLogin" 9 | 10 | func CallAWSIamAuthLogin(httpClient *resty.Client, request AwsIamAuthLoginRequest) (credential MachineIdentityAuthLoginResponse, e error) { 11 | var responseData MachineIdentityAuthLoginResponse 12 | 13 | clonedClient := httpClient.Clone() 14 | clonedClient.SetAuthToken("") 15 | clonedClient.SetAuthScheme("") 16 | 17 | response, err := clonedClient.R(). 18 | SetResult(&responseData). 19 | SetBody(request). 20 | Post("/v1/auth/aws-auth/login") 21 | 22 | if err != nil { 23 | return MachineIdentityAuthLoginResponse{}, errors.NewRequestError(callAWSIamAuthLoginOperation, err) 24 | } 25 | 26 | if response.IsError() { 27 | return MachineIdentityAuthLoginResponse{}, errors.NewAPIErrorWithResponse(callAWSIamAuthLoginOperation, response) 28 | } 29 | 30 | return responseData, nil 31 | } 32 | -------------------------------------------------------------------------------- /packages/api/auth/azure_auth_login.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | ) 7 | 8 | const azureAuthLoginOperation = "CallAzureAuthLogin" 9 | 10 | func CallAzureAuthLogin(httpClient *resty.Client, request AzureAuthLoginRequest) (credential MachineIdentityAuthLoginResponse, e error) { 11 | var responseData MachineIdentityAuthLoginResponse 12 | 13 | clonedClient := httpClient.Clone() 14 | clonedClient.SetAuthToken("") 15 | clonedClient.SetAuthScheme("") 16 | 17 | response, err := clonedClient.R(). 18 | SetResult(&responseData). 19 | SetBody(request). 20 | Post("/v1/auth/azure-auth/login") 21 | 22 | if err != nil { 23 | return MachineIdentityAuthLoginResponse{}, errors.NewRequestError(azureAuthLoginOperation, err) 24 | } 25 | 26 | if response.IsError() { 27 | return MachineIdentityAuthLoginResponse{}, errors.NewAPIErrorWithResponse(azureAuthLoginOperation, response) 28 | } 29 | 30 | return responseData, nil 31 | } 32 | -------------------------------------------------------------------------------- /packages/api/auth/gcp_id_token_auth_login.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | ) 7 | 8 | const callGCPAuthLoginOperation = "CallGCPAuthLogin" 9 | 10 | func CallGCPAuthLogin(httpClient *resty.Client, request GCPAuthLoginRequest) (credential MachineIdentityAuthLoginResponse, e error) { 11 | var responseData MachineIdentityAuthLoginResponse 12 | 13 | clonedClient := httpClient.Clone() 14 | clonedClient.SetAuthToken("") 15 | clonedClient.SetAuthScheme("") 16 | 17 | response, err := clonedClient.R(). 18 | SetResult(&responseData). 19 | SetBody(request). 20 | Post("/v1/auth/gcp-auth/login") 21 | 22 | if err != nil { 23 | return MachineIdentityAuthLoginResponse{}, errors.NewRequestError(callGCPAuthLoginOperation, err) 24 | } 25 | 26 | if response.IsError() { 27 | return MachineIdentityAuthLoginResponse{}, errors.NewAPIErrorWithResponse(callGCPAuthLoginOperation, response) 28 | } 29 | 30 | return responseData, nil 31 | } 32 | -------------------------------------------------------------------------------- /packages/api/auth/jwt_auth_login.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | ) 7 | 8 | const callJwtAuthLoginOperation = "CallJwtAuthLogin" 9 | 10 | func CallJwtAuthLogin(httpClient *resty.Client, request JwtAuthLoginRequest) (credential MachineIdentityAuthLoginResponse, e error) { 11 | var responseData MachineIdentityAuthLoginResponse 12 | 13 | clonedClient := httpClient.Clone() 14 | clonedClient.SetAuthToken("") 15 | clonedClient.SetAuthScheme("") 16 | 17 | response, err := clonedClient.R(). 18 | SetResult(&responseData). 19 | SetBody(request). 20 | Post("/v1/auth/jwt-auth/login") 21 | 22 | if err != nil { 23 | return responseData, errors.NewRequestError(callJwtAuthLoginOperation, err) 24 | } 25 | 26 | if response.IsError() { 27 | return responseData, errors.NewAPIErrorWithResponse(callJwtAuthLoginOperation, response) 28 | } 29 | 30 | return responseData, nil 31 | } 32 | -------------------------------------------------------------------------------- /packages/api/auth/kubernetes_auth_login.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | ) 7 | 8 | const callKubernetesAuthLoginOperation = "CallKubernetesAuthLogin" 9 | 10 | func CallKubernetesAuthLogin(httpClient *resty.Client, request KubernetesAuthLoginRequest) (credential MachineIdentityAuthLoginResponse, e error) { 11 | var responseData MachineIdentityAuthLoginResponse 12 | 13 | clonedClient := httpClient.Clone() 14 | clonedClient.SetAuthToken("") 15 | clonedClient.SetAuthScheme("") 16 | 17 | response, err := clonedClient.R(). 18 | SetResult(&responseData). 19 | SetBody(request). 20 | Post("/v1/auth/kubernetes-auth/login") 21 | 22 | if err != nil { 23 | return MachineIdentityAuthLoginResponse{}, errors.NewRequestError(callKubernetesAuthLoginOperation, err) 24 | } 25 | 26 | if response.IsError() { 27 | return MachineIdentityAuthLoginResponse{}, errors.NewAPIErrorWithResponse(callKubernetesAuthLoginOperation, response) 28 | } 29 | 30 | return responseData, nil 31 | } 32 | -------------------------------------------------------------------------------- /packages/api/auth/models.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | // JWT auth: 4 | type JwtAuthLoginRequest struct { 5 | IdentityID string `json:"identityId"` 6 | JWT string `json:"jwt"` 7 | } 8 | 9 | // Revoke access token: 10 | type RevokeAccessTokenRequest struct { 11 | AccessToken string `json:"accessToken"` 12 | } 13 | 14 | type RevokeAccessTokenResponse struct { 15 | Message string `json:"message"` 16 | } 17 | 18 | // Universal auth: 19 | type UniversalAuthLoginRequest struct { 20 | ClientID string `json:"clientId"` 21 | ClientSecret string `json:"clientSecret"` 22 | } 23 | 24 | // Kubernetes auth: 25 | type KubernetesAuthLoginRequest struct { 26 | IdentityID string `json:"identityId"` 27 | JWT string `json:"jwt"` 28 | } 29 | 30 | type AzureAuthLoginRequest struct { 31 | IdentityID string `json:"identityId"` 32 | JWT string `json:"jwt"` 33 | } 34 | 35 | type AwsIamAuthLoginRequest struct { 36 | HTTPRequestMethod string `json:"iamHttpRequestMethod"` 37 | IamRequestBody string `json:"iamRequestBody"` 38 | IamRequestHeaders string `json:"iamRequestHeaders"` 39 | IdentityId string `json:"identityId"` 40 | } 41 | 42 | type GCPAuthLoginRequest struct { 43 | IdentityID string `json:"identityId"` 44 | JWT string `json:"jwt"` 45 | } 46 | 47 | type OidcAuthLoginRequest struct { 48 | IdentityID string `json:"identityId"` 49 | JWT string `json:"jwt"` 50 | } 51 | 52 | type MachineIdentityAuthLoginResponse struct { 53 | AccessToken string `json:"accessToken"` 54 | ExpiresIn int64 `json:"expiresIn"` 55 | AccessTokenMaxTTL int64 `json:"accessTokenMaxTTL"` 56 | TokenType string `json:"tokenType"` 57 | } 58 | 59 | type RenewAccessTokenRequest struct { 60 | AccessToken string `json:"accessToken"` 61 | } 62 | -------------------------------------------------------------------------------- /packages/api/auth/oidc_auth_login.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | ) 7 | 8 | const callOidcAuthLoginOperation = "CallOidcAuthLogin" 9 | 10 | func CallOidcAuthLogin(httpClient *resty.Client, request OidcAuthLoginRequest) (credential MachineIdentityAuthLoginResponse, e error) { 11 | var responseData MachineIdentityAuthLoginResponse 12 | 13 | clonedClient := httpClient.Clone() 14 | clonedClient.SetAuthToken("") 15 | clonedClient.SetAuthScheme("") 16 | 17 | response, err := clonedClient.R(). 18 | SetResult(&responseData). 19 | SetBody(request). 20 | Post("/v1/auth/oidc-auth/login") 21 | 22 | if err != nil { 23 | return MachineIdentityAuthLoginResponse{}, errors.NewRequestError(callOidcAuthLoginOperation, err) 24 | } 25 | 26 | if response.IsError() { 27 | return MachineIdentityAuthLoginResponse{}, errors.NewAPIErrorWithResponse(callOidcAuthLoginOperation, response) 28 | } 29 | 30 | return responseData, nil 31 | } 32 | -------------------------------------------------------------------------------- /packages/api/auth/renew_access_token.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | ) 7 | 8 | const callRenewAccessToken = "CallRenewAccessToken" 9 | 10 | func CallRenewAccessToken(httpClient *resty.Client, request RenewAccessTokenRequest) (credential MachineIdentityAuthLoginResponse, e error) { 11 | var responseData MachineIdentityAuthLoginResponse 12 | 13 | clonedClient := httpClient.Clone() 14 | clonedClient.SetAuthToken("") 15 | clonedClient.SetAuthScheme("") 16 | 17 | response, err := clonedClient.R(). 18 | SetResult(&responseData). 19 | SetBody(request). 20 | Post("/v1/auth/token/renew") 21 | 22 | if err != nil { 23 | return responseData, errors.NewRequestError(callRenewAccessToken, err) 24 | } 25 | 26 | if response.IsError() { 27 | return responseData, errors.NewAPIErrorWithResponse(callRenewAccessToken, response) 28 | } 29 | 30 | return responseData, nil 31 | } 32 | -------------------------------------------------------------------------------- /packages/api/auth/revoke_access_token.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | ) 7 | 8 | const callRevokeAccessTokenOperation = "CallRevokeAccessToken" 9 | 10 | func CallRevokeAccessToken(httpClient *resty.Client, request RevokeAccessTokenRequest) (RevokeAccessTokenResponse, error) { 11 | var responseData RevokeAccessTokenResponse 12 | 13 | response, err := httpClient.R(). 14 | SetResult(&responseData). 15 | SetBody(request). 16 | Post("/v1/auth/token/revoke") 17 | 18 | if err != nil { 19 | return responseData, errors.NewRequestError(callRevokeAccessTokenOperation, err) 20 | } 21 | 22 | if response.IsError() { 23 | return responseData, errors.NewAPIErrorWithResponse(callRevokeAccessTokenOperation, response) 24 | } 25 | 26 | return responseData, nil 27 | } 28 | -------------------------------------------------------------------------------- /packages/api/auth/universal_auth_login.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | ) 7 | 8 | const callUniversalAuthLoginOperation = "CallUniversalAuthLogin" 9 | 10 | func CallUniversalAuthLogin(httpClient *resty.Client, request UniversalAuthLoginRequest) (credential MachineIdentityAuthLoginResponse, e error) { 11 | var responseData MachineIdentityAuthLoginResponse 12 | 13 | clonedClient := httpClient.Clone() 14 | clonedClient.SetAuthToken("") 15 | clonedClient.SetAuthScheme("") 16 | 17 | response, err := clonedClient.R(). 18 | SetResult(&responseData). 19 | SetBody(request). 20 | Post("/v1/auth/universal-auth/login") 21 | 22 | if err != nil { 23 | return responseData, errors.NewRequestError(callUniversalAuthLoginOperation, err) 24 | } 25 | 26 | if response.IsError() { 27 | return responseData, errors.NewAPIErrorWithResponse(callUniversalAuthLoginOperation, response) 28 | } 29 | 30 | return responseData, nil 31 | } 32 | -------------------------------------------------------------------------------- /packages/api/dynamic_secrets/create_lease.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | ) 7 | 8 | const callCreateDynamicSecretLeaseV1Operation = "CallCreateDynamicSecretLeaseV1" 9 | 10 | func CallCreateDynamicSecretLeaseV1(httpClient *resty.Client, request CreateDynamicSecretLeaseV1Request) (CreateDynamicSecretLeaseV1Response, error) { 11 | 12 | createResponse := CreateDynamicSecretLeaseV1Response{} 13 | 14 | req := httpClient.R(). 15 | SetResult(&createResponse). 16 | SetBody(request) 17 | 18 | res, err := req.Post("/v1/dynamic-secrets/leases") 19 | 20 | if err != nil { 21 | return CreateDynamicSecretLeaseV1Response{}, errors.NewRequestError(callCreateDynamicSecretLeaseV1Operation, err) 22 | } 23 | 24 | if res.IsError() { 25 | return CreateDynamicSecretLeaseV1Response{}, errors.NewAPIErrorWithResponse(callCreateDynamicSecretLeaseV1Operation, res) 26 | } 27 | 28 | return createResponse, nil 29 | } 30 | -------------------------------------------------------------------------------- /packages/api/dynamic_secrets/delete_lease.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | ) 7 | 8 | const callDeleteDynamicSecretLeaseV1Operation = "CallDeleteDynamicSecretLeaseV1" 9 | 10 | func CallDeleteDynamicSecretLeaseV1(httpClient *resty.Client, request DeleteDynamicSecretLeaseV1Request) (DeleteDynamicSecretLeaseV1Response, error) { 11 | 12 | deleteResponse := DeleteDynamicSecretLeaseV1Response{} 13 | 14 | req := httpClient.R(). 15 | SetResult(&deleteResponse). 16 | SetBody(request) 17 | 18 | res, err := req.Delete("/v1/dynamic-secrets/leases/" + request.LeaseId) 19 | 20 | if err != nil { 21 | return DeleteDynamicSecretLeaseV1Response{}, errors.NewRequestError(callDeleteDynamicSecretLeaseV1Operation, err) 22 | } 23 | 24 | if res.IsError() { 25 | return DeleteDynamicSecretLeaseV1Response{}, errors.NewAPIErrorWithResponse(callDeleteDynamicSecretLeaseV1Operation, res) 26 | } 27 | 28 | return deleteResponse, nil 29 | } 30 | -------------------------------------------------------------------------------- /packages/api/dynamic_secrets/get_lease_by_id.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | ) 7 | 8 | const callGetDynamicSecretLeaseByIdV1Operation = "CallGetDynamicSecretLeaseByIdV1" 9 | 10 | func CallGetByDynamicSecretByIdLeaseV1(httpClient *resty.Client, request GetDynamicSecretLeaseByIdV1Request) (GetDynamicSecretLeaseByIdV1Response, error) { 11 | 12 | getByIdResponse := GetDynamicSecretLeaseByIdV1Response{} 13 | 14 | req := httpClient.R(). 15 | SetResult(&getByIdResponse). 16 | SetQueryParams(map[string]string{ 17 | "projectSlug": request.ProjectSlug, 18 | "environmentSlug": request.EnvironmentSlug, 19 | "path": request.SecretPath, 20 | }) 21 | 22 | res, err := req.Get("/v1/dynamic-secrets/leases/" + request.LeaseId) 23 | 24 | if err != nil { 25 | return GetDynamicSecretLeaseByIdV1Response{}, errors.NewRequestError(callGetDynamicSecretLeaseByIdV1Operation, err) 26 | } 27 | 28 | if res.IsError() { 29 | return GetDynamicSecretLeaseByIdV1Response{}, errors.NewAPIErrorWithResponse(callGetDynamicSecretLeaseByIdV1Operation, res) 30 | } 31 | 32 | return getByIdResponse, nil 33 | } 34 | -------------------------------------------------------------------------------- /packages/api/dynamic_secrets/get_secret_by_name.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | ) 7 | 8 | const callGetDynamicSecretByNameV1Operation = "CallGetDynamicSecretSecretByNameV1" 9 | 10 | func CallGetDynamicSecretByNameV1(httpClient *resty.Client, request GetDynamicSecretByNameV1Request) (GetDynamicSecretByNameV1Response, error) { 11 | 12 | getByNameResponse := GetDynamicSecretByNameV1Response{} 13 | 14 | req := httpClient.R(). 15 | SetResult(&getByNameResponse).SetQueryParams(map[string]string{ 16 | "projectSlug": request.ProjectSlug, 17 | "environmentSlug": request.EnvironmentSlug, 18 | "path": request.SecretPath, 19 | }) 20 | 21 | res, err := req.Get("/v1/dynamic-secrets/" + request.DynamicSecretName) 22 | 23 | if err != nil { 24 | return GetDynamicSecretByNameV1Response{}, errors.NewRequestError(callGetDynamicSecretByNameV1Operation, err) 25 | } 26 | 27 | if res.IsError() { 28 | return GetDynamicSecretByNameV1Response{}, errors.NewAPIErrorWithResponse(callGetDynamicSecretByNameV1Operation, res) 29 | } 30 | 31 | return getByNameResponse, nil 32 | } 33 | -------------------------------------------------------------------------------- /packages/api/dynamic_secrets/list_lease.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | ) 7 | 8 | const callListDynamicSecretLeaseV1Operation = "CallListDynamicSecretLeaseV1" 9 | 10 | func CallListDynamicSecretLeaseV1(httpClient *resty.Client, request ListDynamicSecretLeaseV1Request) (ListDynamicSecretLeaseV1Response, error) { 11 | 12 | listResponse := ListDynamicSecretLeaseV1Response{} 13 | 14 | req := httpClient.R(). 15 | SetResult(&listResponse). 16 | SetQueryParams(map[string]string{ 17 | "projectSlug": request.ProjectSlug, 18 | "environmentSlug": request.EnvironmentSlug, 19 | "path": request.SecretPath, 20 | }) 21 | 22 | res, err := req.Get("/v1/dynamic-secrets/" + request.DynamicSecretName + "/leases") 23 | 24 | if err != nil { 25 | return ListDynamicSecretLeaseV1Response{}, errors.NewRequestError(callListDynamicSecretLeaseV1Operation, err) 26 | } 27 | 28 | if res.IsError() { 29 | return ListDynamicSecretLeaseV1Response{}, errors.NewAPIErrorWithResponse(callListDynamicSecretLeaseV1Operation, res) 30 | } 31 | 32 | return listResponse, nil 33 | } 34 | -------------------------------------------------------------------------------- /packages/api/dynamic_secrets/list_secrets.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | ) 7 | 8 | const callListDynamicSecretsV1Operation = "CallListDynamicSecretSecretsV1" 9 | 10 | func CallListDynamicSecretsV1(httpClient *resty.Client, request ListDynamicSecretsV1Request) (ListDynamicSecretsV1Response, error) { 11 | 12 | listDynamicSecretResponse := ListDynamicSecretsV1Response{} 13 | 14 | req := httpClient.R(). 15 | SetResult(&listDynamicSecretResponse). 16 | SetQueryParams(map[string]string{ 17 | "projectSlug": request.ProjectSlug, 18 | "environmentSlug": request.EnvironmentSlug, 19 | "path": request.SecretPath, 20 | }) 21 | 22 | res, err := req.Get("/v1/dynamic-secrets") 23 | 24 | if err != nil { 25 | return ListDynamicSecretsV1Response{}, errors.NewRequestError(callListDynamicSecretsV1Operation, err) 26 | } 27 | 28 | if res.IsError() { 29 | return ListDynamicSecretsV1Response{}, errors.NewAPIErrorWithResponse(callListDynamicSecretsV1Operation, res) 30 | } 31 | 32 | return listDynamicSecretResponse, nil 33 | } 34 | -------------------------------------------------------------------------------- /packages/api/dynamic_secrets/models.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/infisical/go-sdk/packages/models" 5 | ) 6 | 7 | type CreateDynamicSecretLeaseV1Request struct { 8 | DynamicSecretName string `json:"dynamicSecretName"` 9 | ProjectSlug string `json:"projectSlug"` 10 | TTL string `json:"ttl"` 11 | SecretPath string `json:"path"` 12 | EnvironmentSlug string `json:"environmentSlug"` 13 | Config map[string]any `json:"config"` 14 | } 15 | 16 | type CreateDynamicSecretLeaseV1Response struct { 17 | Lease models.DynamicSecretLease `json:"lease"` 18 | DynamicSecret models.DynamicSecret `json:"dynamicSecret"` 19 | Data map[string]any `json:"data"` 20 | } 21 | 22 | type DeleteDynamicSecretLeaseV1Request struct { 23 | LeaseId string `json:"leaseId"` 24 | ProjectSlug string `json:"projectSlug"` 25 | SecretPath string `json:"path"` 26 | EnvironmentSlug string `json:"environmentSlug"` 27 | IsForced bool `json:"isForced"` 28 | } 29 | 30 | type DeleteDynamicSecretLeaseV1Response struct { 31 | Lease models.DynamicSecretLease `json:"lease"` 32 | } 33 | 34 | type RenewDynamicSecretLeaseV1Request struct { 35 | LeaseId string `json:"leaseId"` 36 | TTL string `json:"ttl"` 37 | ProjectSlug string `json:"projectSlug"` 38 | SecretPath string `json:"path"` 39 | EnvironmentSlug string `json:"environmentSlug"` 40 | IsForced bool `json:"isForced"` 41 | } 42 | 43 | type RenewDynamicSecretLeaseV1Response struct { 44 | Lease models.DynamicSecretLease `json:"lease"` 45 | } 46 | 47 | type GetDynamicSecretLeaseByIdV1Request struct { 48 | LeaseId string `json:"leaseId"` 49 | ProjectSlug string `json:"projectSlug"` 50 | SecretPath string `json:"path"` 51 | EnvironmentSlug string `json:"environmentSlug"` 52 | } 53 | 54 | type GetDynamicSecretLeaseByIdV1Response struct { 55 | Lease models.DynamicSecretLeaseWithDynamicSecret `json:"lease"` 56 | } 57 | 58 | type ListDynamicSecretLeaseV1Request struct { 59 | DynamicSecretName string `json:"secretName"` 60 | ProjectSlug string `json:"projectSlug"` 61 | SecretPath string `json:"path"` 62 | EnvironmentSlug string `json:"environmentSlug"` 63 | } 64 | 65 | type ListDynamicSecretLeaseV1Response struct { 66 | Leases []models.DynamicSecretLease `json:"leases"` 67 | } 68 | 69 | type GetDynamicSecretByNameV1Request struct { 70 | DynamicSecretName string `json:"secretName"` 71 | ProjectSlug string `json:"projectSlug"` 72 | SecretPath string `json:"path"` 73 | EnvironmentSlug string `json:"environmentSlug"` 74 | } 75 | 76 | type GetDynamicSecretByNameV1Response struct { 77 | DynamicSecret models.DynamicSecret `json:"dynamicSecret"` 78 | } 79 | 80 | type ListDynamicSecretsV1Request struct { 81 | ProjectSlug string `json:"projectSlug"` 82 | SecretPath string `json:"path"` 83 | EnvironmentSlug string `json:"environmentSlug"` 84 | } 85 | 86 | type ListDynamicSecretsV1Response struct { 87 | DynamicSecrets []models.DynamicSecret `json:"dynamicSecrets"` 88 | } 89 | -------------------------------------------------------------------------------- /packages/api/dynamic_secrets/renew_lease.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | ) 7 | 8 | const callRenewDynamicSecretLeaseV1Operation = "CallRenewDynamicSecretLeaseV1" 9 | 10 | func CallRenewDynamicSecretLeaseV1(httpClient *resty.Client, request RenewDynamicSecretLeaseV1Request) (RenewDynamicSecretLeaseV1Response, error) { 11 | 12 | renewResponse := RenewDynamicSecretLeaseV1Response{} 13 | 14 | req := httpClient.R(). 15 | SetResult(&renewResponse). 16 | SetBody(request) 17 | 18 | res, err := req.Post("/v1/dynamic-secrets/leases/" + request.LeaseId + "/renew") 19 | 20 | if err != nil { 21 | return RenewDynamicSecretLeaseV1Response{}, errors.NewRequestError(callRenewDynamicSecretLeaseV1Operation, err) 22 | } 23 | 24 | if res.IsError() { 25 | return RenewDynamicSecretLeaseV1Response{}, errors.NewAPIErrorWithResponse(callRenewDynamicSecretLeaseV1Operation, res) 26 | } 27 | 28 | return renewResponse, nil 29 | } 30 | -------------------------------------------------------------------------------- /packages/api/folders/create_folder.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | ) 7 | 8 | const callCreateFolderV1Operation = "CallCreateFolderV1" 9 | 10 | func CallCreateFolderV1(httpClient *resty.Client, request CreateFolderV1Request) (CreateFolderV1Response, error) { 11 | 12 | createResponse := CreateFolderV1Response{} 13 | 14 | req := httpClient.R(). 15 | SetResult(&createResponse). 16 | SetBody(request) 17 | 18 | res, err := req.Post("/v1/folders") 19 | 20 | if err != nil { 21 | return CreateFolderV1Response{}, errors.NewRequestError(callCreateFolderV1Operation, err) 22 | } 23 | 24 | if res.IsError() { 25 | return CreateFolderV1Response{}, errors.NewAPIErrorWithResponse(callCreateFolderV1Operation, res) 26 | } 27 | 28 | return createResponse, nil 29 | } 30 | -------------------------------------------------------------------------------- /packages/api/folders/delete_folder.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/go-resty/resty/v2" 7 | "github.com/infisical/go-sdk/packages/errors" 8 | ) 9 | 10 | const callDeleteFolderV1Operation = "CallDeleteFolderV1" 11 | 12 | func CallDeleteFolderV1(httpClient *resty.Client, request DeleteFolderV1Request) (DeleteFolderV1Response, error) { 13 | 14 | deleteResponse := DeleteFolderV1Response{} 15 | 16 | // Either folderID or folderName must be provided 17 | var folderIdOrName string 18 | if request.FolderID != "" { 19 | folderIdOrName = request.FolderID 20 | } else if request.FolderName != "" { 21 | folderIdOrName = request.FolderName 22 | } else { 23 | return DeleteFolderV1Response{}, fmt.Errorf("CallDeleteFolderV1: Either folderID or folderName must be provided") 24 | } 25 | 26 | req := httpClient.R(). 27 | SetResult(&deleteResponse). 28 | SetBody(request) 29 | 30 | res, err := req.Delete(fmt.Sprintf("/v1/folders/%s", folderIdOrName)) 31 | 32 | if err != nil { 33 | return DeleteFolderV1Response{}, errors.NewRequestError(callDeleteFolderV1Operation, err) 34 | } 35 | 36 | if res.IsError() { 37 | return DeleteFolderV1Response{}, errors.NewAPIErrorWithResponse(callDeleteFolderV1Operation, res) 38 | } 39 | 40 | return deleteResponse, nil 41 | } 42 | -------------------------------------------------------------------------------- /packages/api/folders/list_folders.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | ) 7 | 8 | const callListFoldersV1Operation = "CallListFoldersV1" 9 | 10 | func CallListFoldersV1(httpClient *resty.Client, request ListFoldersV1Request) (ListFoldersV1Response, error) { 11 | 12 | secretsResponse := ListFoldersV1Response{} 13 | 14 | queryParams := map[string]string{ 15 | "workspaceId": request.ProjectID, 16 | "environment": request.Environment, 17 | } 18 | 19 | if request.Path != "" { 20 | queryParams["path"] = request.Path 21 | } 22 | 23 | res, err := httpClient.R(). 24 | SetResult(&secretsResponse). 25 | SetQueryParams(queryParams).Get("/v1/folders") 26 | 27 | if err != nil { 28 | return ListFoldersV1Response{}, errors.NewRequestError(callListFoldersV1Operation, err) 29 | } 30 | 31 | if res.IsError() { 32 | return ListFoldersV1Response{}, errors.NewAPIErrorWithResponse(callListFoldersV1Operation, res) 33 | } 34 | 35 | return secretsResponse, nil 36 | } 37 | -------------------------------------------------------------------------------- /packages/api/folders/models.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/infisical/go-sdk/packages/models" 5 | ) 6 | 7 | // List folders 8 | type ListFoldersV1Request struct { 9 | ProjectID string `json:"workspaceId"` 10 | Environment string `json:"environment"` 11 | Path string `json:"path,omitempty"` 12 | } 13 | 14 | type ListFoldersV1Response struct { 15 | Folders []models.Folder `json:"folders"` 16 | } 17 | 18 | // Update folder 19 | type UpdateFolderV1Request struct { 20 | FolderID string `json:"-"` 21 | 22 | ProjectID string `json:"workspaceId"` 23 | Environment string `json:"environment"` 24 | NewName string `json:"name"` 25 | Path string `json:"path,omitempty"` 26 | } 27 | 28 | type UpdateFolderV1Response struct { 29 | Folder models.Folder `json:"folder"` 30 | } 31 | 32 | // Create folder 33 | type CreateFolderV1Request struct { 34 | ProjectID string `json:"workspaceId"` 35 | Environment string `json:"environment"` 36 | Name string `json:"name"` 37 | Path string `json:"path,omitempty"` 38 | } 39 | 40 | type CreateFolderV1Response struct { 41 | Folder models.Folder `json:"folder"` 42 | } 43 | 44 | // Delete folder 45 | type DeleteFolderV1Request struct { 46 | // Either FolderID or folderName must be provided 47 | FolderID string `json:"-"` 48 | FolderName string `json:"-"` 49 | 50 | ProjectID string `json:"workspaceId"` 51 | Environment string `json:"environment"` 52 | Path string `json:"path,omitempty"` 53 | } 54 | 55 | type DeleteFolderV1Response struct { 56 | Folder models.Folder `json:"folder"` 57 | } 58 | -------------------------------------------------------------------------------- /packages/api/folders/update_folder.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/go-resty/resty/v2" 7 | "github.com/infisical/go-sdk/packages/errors" 8 | ) 9 | 10 | const callUpdateFolderV1Operation = "CallUpdateFolderV1" 11 | 12 | func CallUpdateFolderV1(httpClient *resty.Client, request UpdateFolderV1Request) (UpdateFolderV1Response, error) { 13 | 14 | updateResponse := UpdateFolderV1Response{} 15 | 16 | req := httpClient.R(). 17 | SetResult(&updateResponse). 18 | SetBody(request) 19 | 20 | res, err := req.Patch(fmt.Sprintf("/v1/folders/%s", request.FolderID)) 21 | 22 | if err != nil { 23 | return UpdateFolderV1Response{}, errors.NewRequestError(callUpdateFolderV1Operation, err) 24 | } 25 | 26 | if res.IsError() { 27 | return UpdateFolderV1Response{}, errors.NewAPIErrorWithResponse(callUpdateFolderV1Operation, res) 28 | } 29 | 30 | return updateResponse, nil 31 | } 32 | -------------------------------------------------------------------------------- /packages/api/kms/create_key.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | ) 7 | 8 | const callKmsCreateKeyOperationV1 = "CallKmsCreateKeyV1" 9 | 10 | func CallKmsCreateKeyV1(httpClient *resty.Client, request KmsCreateKeyV1Request) (KmsCreateKeyV1Response, error) { 11 | kmsCreateKeyResponse := KmsCreateKeyV1Response{} 12 | 13 | res, err := httpClient.R(). 14 | SetResult(&kmsCreateKeyResponse). 15 | SetBody(request). 16 | Post("/v1/kms/keys") 17 | 18 | if err != nil { 19 | return KmsCreateKeyV1Response{}, errors.NewRequestError(callKmsCreateKeyOperationV1, err) 20 | } 21 | 22 | if res.IsError() { 23 | return KmsCreateKeyV1Response{}, errors.NewAPIErrorWithResponse(callKmsCreateKeyOperationV1, res) 24 | } 25 | 26 | return kmsCreateKeyResponse, nil 27 | } 28 | -------------------------------------------------------------------------------- /packages/api/kms/decrypt_data.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/go-resty/resty/v2" 7 | "github.com/infisical/go-sdk/packages/errors" 8 | ) 9 | 10 | const callKmsDecryptDataOperationV1 = "CallKmsDecryptDataV1" 11 | 12 | func CallKmsDecryptDataV1(httpClient *resty.Client, request KmsDecryptDataV1Request) (KmsDecryptDataV1Response, error) { 13 | kmsDecryptDataResponse := KmsDecryptDataV1Response{} 14 | 15 | res, err := httpClient.R(). 16 | SetResult(&kmsDecryptDataResponse). 17 | SetBody(request). 18 | Post(fmt.Sprintf("/v1/kms/keys/%s/decrypt", request.KeyId)) 19 | 20 | if err != nil { 21 | return KmsDecryptDataV1Response{}, errors.NewRequestError(callKmsDecryptDataOperationV1, err) 22 | } 23 | 24 | if res.IsError() { 25 | return KmsDecryptDataV1Response{}, errors.NewAPIErrorWithResponse(callKmsDecryptDataOperationV1, res) 26 | } 27 | 28 | return kmsDecryptDataResponse, nil 29 | } 30 | -------------------------------------------------------------------------------- /packages/api/kms/delete_key.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/go-resty/resty/v2" 7 | "github.com/infisical/go-sdk/packages/errors" 8 | ) 9 | 10 | const callKmsDeleteKeyOperationV1 = "CallKmsDeleteKeyV1" 11 | 12 | func CallKmsDeleteKeyV1(httpClient *resty.Client, request KmsDeleteKeyV1Request) (KmsDeleteKeyV1Response, error) { 13 | kmsDeleteKeyResponse := KmsDeleteKeyV1Response{} 14 | 15 | res, err := httpClient.R(). 16 | SetResult(&kmsDeleteKeyResponse). 17 | SetBody(request). 18 | Delete(fmt.Sprintf("/v1/kms/keys/%s", request.KeyId)) 19 | 20 | if err != nil { 21 | return KmsDeleteKeyV1Response{}, errors.NewRequestError(callKmsDeleteKeyOperationV1, err) 22 | } 23 | 24 | if res.IsError() { 25 | return KmsDeleteKeyV1Response{}, errors.NewAPIErrorWithResponse(callKmsDeleteKeyOperationV1, res) 26 | } 27 | 28 | return kmsDeleteKeyResponse, nil 29 | } 30 | -------------------------------------------------------------------------------- /packages/api/kms/encrypt_data.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/go-resty/resty/v2" 7 | "github.com/infisical/go-sdk/packages/errors" 8 | ) 9 | 10 | const callKmsEncryptDataOperationV1 = "CallKmsEncryptDataV1" 11 | 12 | func CallKmsEncryptDataV1(httpClient *resty.Client, request KmsEncryptDataV1Request) (KmsEncryptDataV1Response, error) { 13 | kmsEncryptDataResponse := KmsEncryptDataV1Response{} 14 | 15 | res, err := httpClient.R(). 16 | SetResult(&kmsEncryptDataResponse). 17 | SetBody(request). 18 | Post(fmt.Sprintf("/v1/kms/keys/%s/encrypt", request.KeyId)) 19 | 20 | if err != nil { 21 | return KmsEncryptDataV1Response{}, errors.NewRequestError(callKmsEncryptDataOperationV1, err) 22 | } 23 | 24 | if res.IsError() { 25 | return KmsEncryptDataV1Response{}, errors.NewAPIErrorWithResponse(callKmsEncryptDataOperationV1, res) 26 | } 27 | 28 | return kmsEncryptDataResponse, nil 29 | } 30 | -------------------------------------------------------------------------------- /packages/api/kms/get_key_by_name.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/go-resty/resty/v2" 7 | "github.com/infisical/go-sdk/packages/errors" 8 | ) 9 | 10 | const callKmsGetKeyByNameOperationV1 = "CallKmsGetKeyByNameV1" 11 | 12 | func CallKmsGetKeyByNameV1(httpClient *resty.Client, request KmsGetKeyByNameV1Request) (KmsGetKeyV1Response, error) { 13 | kmsGetKeyByNameResponse := KmsGetKeyV1Response{} 14 | 15 | res, err := httpClient.R(). 16 | SetResult(&kmsGetKeyByNameResponse). 17 | Get(fmt.Sprintf("/v1/kms/keys/key-name/%s?projectId=%s", request.KeyName, request.ProjectId)) 18 | 19 | if err != nil { 20 | return KmsGetKeyV1Response{}, errors.NewRequestError(callKmsGetKeyByNameOperationV1, err) 21 | } 22 | 23 | if res.IsError() { 24 | return KmsGetKeyV1Response{}, errors.NewAPIErrorWithResponse(callKmsGetKeyByNameOperationV1, res) 25 | } 26 | 27 | return kmsGetKeyByNameResponse, nil 28 | } 29 | -------------------------------------------------------------------------------- /packages/api/kms/get_public_key.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/go-resty/resty/v2" 7 | "github.com/infisical/go-sdk/packages/errors" 8 | ) 9 | 10 | const callKmsGetPublicKeyOperationV1 = "CallKmsGetPublicKeyV1" 11 | 12 | func CallKmsGetPublicKeyV1(httpClient *resty.Client, request KmsGetPublicKeyV1Request) (KmsGetPublicKeyV1Response, error) { 13 | kmsGetPublicKeyResponse := KmsGetPublicKeyV1Response{} 14 | 15 | res, err := httpClient.R(). 16 | SetResult(&kmsGetPublicKeyResponse). 17 | Get(fmt.Sprintf("/v1/kms/keys/%s/public-key", request.KeyId)) 18 | 19 | if err != nil { 20 | return KmsGetPublicKeyV1Response{}, errors.NewRequestError(callKmsGetPublicKeyOperationV1, err) 21 | } 22 | 23 | if res.IsError() { 24 | return KmsGetPublicKeyV1Response{}, errors.NewAPIErrorWithResponse(callKmsGetPublicKeyOperationV1, res) 25 | } 26 | 27 | return kmsGetPublicKeyResponse, nil 28 | } 29 | -------------------------------------------------------------------------------- /packages/api/kms/get_signing_algorithms.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/go-resty/resty/v2" 7 | 8 | "github.com/infisical/go-sdk/packages/errors" 9 | ) 10 | 11 | const callKmsGetSigningAlgorithmsOperationV1 = "CallKmsGetSigningAlgorithmsV1" 12 | 13 | func CallKmsGetSigningAlgorithmsV1(httpClient *resty.Client, request KmsListSigningAlgorithmsV1Request) (KmsListSigningAlgorithmsV1Response, error) { 14 | kmsListSigningAlgorithmsResponse := KmsListSigningAlgorithmsV1Response{} 15 | 16 | res, err := httpClient.R(). 17 | SetResult(&kmsListSigningAlgorithmsResponse). 18 | Get(fmt.Sprintf("/v1/kms/keys/%s/signing-algorithms", request.KeyId)) 19 | 20 | if err != nil { 21 | return KmsListSigningAlgorithmsV1Response{}, errors.NewRequestError(callKmsGetSigningAlgorithmsOperationV1, err) 22 | } 23 | 24 | if res.IsError() { 25 | return KmsListSigningAlgorithmsV1Response{}, errors.NewAPIErrorWithResponse(callKmsGetSigningAlgorithmsOperationV1, res) 26 | } 27 | 28 | return kmsListSigningAlgorithmsResponse, nil 29 | } 30 | -------------------------------------------------------------------------------- /packages/api/kms/models.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | type KmsEncryptDataV1Request struct { 4 | KeyId string 5 | Plaintext string `json:"plaintext"` 6 | } 7 | 8 | type KmsEncryptDataV1Response struct { 9 | Ciphertext string `json:"ciphertext"` 10 | } 11 | 12 | type KmsDecryptDataV1Request struct { 13 | KeyId string 14 | Ciphertext string `json:"ciphertext"` 15 | } 16 | 17 | type KmsDecryptDataV1Response struct { 18 | Plaintext string `json:"plaintext"` 19 | } 20 | 21 | type KmsSignDataV1Request struct { 22 | KeyId string 23 | Data string `json:"data"` 24 | SigningAlgorithm string `json:"signingAlgorithm"` 25 | IsDigest bool `json:"isDigest"` 26 | } 27 | 28 | type KmsSignDataV1Response struct { 29 | Signature string `json:"signature"` 30 | KeyId string `json:"keyId"` 31 | SigningAlgorithm string `json:"signingAlgorithm"` 32 | } 33 | 34 | type KmsVerifyDataV1Request struct { 35 | KeyId string 36 | Data string `json:"data"` // Data must be base64 encoded 37 | Signature string `json:"signature"` 38 | SigningAlgorithm string `json:"signingAlgorithm"` 39 | IsDigest bool `json:"isDigest"` 40 | } 41 | 42 | type KmsVerifyDataV1Response struct { 43 | SignatureValid bool `json:"signatureValid"` 44 | KeyId string `json:"keyId"` 45 | SigningAlgorithm string `json:"signingAlgorithm"` 46 | } 47 | 48 | type KmsListSigningAlgorithmsV1Request struct { 49 | KeyId string 50 | } 51 | 52 | type KmsListSigningAlgorithmsV1Response struct { 53 | SigningAlgorithms []string `json:"signingAlgorithms"` 54 | } 55 | 56 | type KmsGetPublicKeyV1Request struct { 57 | KeyId string 58 | } 59 | 60 | type KmsGetPublicKeyV1Response struct { 61 | PublicKey string `json:"publicKey"` 62 | } 63 | 64 | type KmsCreateKeyV1Request struct { 65 | // KeyUsage is the usage of the key. Can be either sign-verify or encrypt-decrypt 66 | KeyUsage string `json:"keyUsage"` 67 | 68 | // Description is the description of the key. 69 | Description string `json:"description"` 70 | 71 | // Name is the name of the key. 72 | Name string `json:"name"` 73 | 74 | // EncryptionAlgorithm is the algorithm that will be used for the key itself. 75 | // `sign-verify algorithms`: `rsa-4096`, `ecc-nist-p256` 76 | // `encrypt-decrypt algorithms`: `aes-256-gcm`, `aes-128-gcm` 77 | EncryptionAlgorithm string `json:"encryptionAlgorithm"` 78 | 79 | // ProjectId is the project ID that the key will be created in. 80 | ProjectId string `json:"projectId"` 81 | } 82 | 83 | type KmsCreateKeyV1Response struct { 84 | Key KmsKey `json:"key"` 85 | } 86 | 87 | type KmsDeleteKeyV1Request struct { 88 | KeyId string 89 | } 90 | 91 | type KmsDeleteKeyV1Response struct { 92 | Key KmsKey `json:"key"` 93 | } 94 | 95 | type KmsGetKeyByNameV1Request struct { 96 | KeyName string 97 | ProjectId string 98 | } 99 | 100 | type KmsGetKeyV1Response struct { 101 | Key KmsKey `json:"key"` 102 | } 103 | 104 | type KmsKey struct { 105 | KeyId string `json:"id"` 106 | Description string `json:"description"` 107 | IsDisabled bool `json:"isDisabled"` 108 | OrgId string `json:"orgId"` 109 | Name string `json:"name"` 110 | ProjectId string `json:"projectId"` 111 | KeyUsage string `json:"keyUsage"` 112 | Version int `json:"version"` 113 | EncryptionAlgorithm string `json:"encryptionAlgorithm"` 114 | } 115 | -------------------------------------------------------------------------------- /packages/api/kms/sign_data.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/go-resty/resty/v2" 7 | "github.com/infisical/go-sdk/packages/errors" 8 | ) 9 | 10 | const callKmsSignDataOperationV1 = "CallKmsSignDataV1" 11 | 12 | func CallKmsSignDataV1(httpClient *resty.Client, request KmsSignDataV1Request) (KmsSignDataV1Response, error) { 13 | kmsSignDataResponse := KmsSignDataV1Response{} 14 | 15 | res, err := httpClient.R(). 16 | SetResult(&kmsSignDataResponse). 17 | SetBody(request). 18 | Post(fmt.Sprintf("/v1/kms/keys/%s/sign", request.KeyId)) 19 | 20 | if err != nil { 21 | return KmsSignDataV1Response{}, errors.NewRequestError(callKmsSignDataOperationV1, err) 22 | } 23 | 24 | if res.IsError() { 25 | return KmsSignDataV1Response{}, errors.NewAPIErrorWithResponse(callKmsSignDataOperationV1, res) 26 | } 27 | 28 | return kmsSignDataResponse, nil 29 | } 30 | -------------------------------------------------------------------------------- /packages/api/kms/verify_data.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/go-resty/resty/v2" 7 | "github.com/infisical/go-sdk/packages/errors" 8 | ) 9 | 10 | const callKmsVerifyDataOperationV1 = "CallKmsVerifyDataV1" 11 | 12 | func CallKmsVerifyDataV1(httpClient *resty.Client, request KmsVerifyDataV1Request) (KmsVerifyDataV1Response, error) { 13 | kmsVerifyDataResponse := KmsVerifyDataV1Response{} 14 | 15 | res, err := httpClient.R(). 16 | SetResult(&kmsVerifyDataResponse). 17 | SetBody(request). 18 | Post(fmt.Sprintf("/v1/kms/keys/%s/verify", request.KeyId)) 19 | 20 | if err != nil { 21 | return KmsVerifyDataV1Response{}, errors.NewRequestError(callKmsVerifyDataOperationV1, err) 22 | } 23 | 24 | if res.IsError() { 25 | return KmsVerifyDataV1Response{}, errors.NewAPIErrorWithResponse(callKmsVerifyDataOperationV1, res) 26 | } 27 | 28 | return kmsVerifyDataResponse, nil 29 | } 30 | -------------------------------------------------------------------------------- /packages/api/secrets/bulk_create_secrets.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | ) 7 | 8 | const callBatchCreateSecretV3RawOperation = "CallBatchCreateSecretV3Raw" 9 | 10 | func CallBatchCreateSecretV3(httpClient *resty.Client, request BatchCreateSecretsV3RawRequest) (BatchCreateSecretsV3RawResponse, error) { 11 | 12 | createBatchResponse := BatchCreateSecretsV3RawResponse{} 13 | 14 | req := httpClient.R(). 15 | SetResult(&createBatchResponse). 16 | SetBody(request) 17 | 18 | res, err := req.Post("/v3/secrets/batch/raw") 19 | 20 | if err != nil { 21 | return BatchCreateSecretsV3RawResponse{}, errors.NewRequestError(callBatchCreateSecretV3RawOperation, err) 22 | } 23 | 24 | if res.IsError() { 25 | return BatchCreateSecretsV3RawResponse{}, errors.NewAPIErrorWithResponse(callBatchCreateSecretV3RawOperation, res) 26 | } 27 | 28 | for idx := range createBatchResponse.Secrets { 29 | 30 | secretPath := request.SecretPath 31 | 32 | if secretPath == "" { 33 | secretPath = "/" 34 | } 35 | 36 | createBatchResponse.Secrets[idx].SecretPath = secretPath 37 | } 38 | 39 | return createBatchResponse, nil 40 | } 41 | -------------------------------------------------------------------------------- /packages/api/secrets/create_secret.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/go-resty/resty/v2" 7 | "github.com/infisical/go-sdk/packages/errors" 8 | ) 9 | 10 | const callCreateSecretV3RawOperation = "CallCreateSecretV3Raw" 11 | 12 | func CallCreateSecretV3(httpClient *resty.Client, request CreateSecretV3RawRequest) (CreateSecretV3RawResponse, error) { 13 | 14 | createResponse := CreateSecretV3RawResponse{} 15 | 16 | req := httpClient.R(). 17 | SetResult(&createResponse). 18 | SetBody(request) 19 | 20 | res, err := req.Post(fmt.Sprintf("/v3/secrets/raw/%s", request.SecretKey)) 21 | 22 | if err != nil { 23 | return CreateSecretV3RawResponse{}, errors.NewRequestError(callCreateSecretV3RawOperation, err) 24 | } 25 | 26 | if res.IsError() { 27 | return CreateSecretV3RawResponse{}, errors.NewAPIErrorWithResponse(callCreateSecretV3RawOperation, res) 28 | } 29 | 30 | return createResponse, nil 31 | } 32 | -------------------------------------------------------------------------------- /packages/api/secrets/delete_secret.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/go-resty/resty/v2" 7 | "github.com/infisical/go-sdk/packages/errors" 8 | ) 9 | 10 | const callDeleteSecretV3RawOperation = "CallDeleteSecretV3Raw" 11 | 12 | func CallDeleteSecretV3(httpClient *resty.Client, request DeleteSecretV3RawRequest) (DeleteSecretV3RawResponse, error) { 13 | 14 | deleteResponse := DeleteSecretV3RawResponse{} 15 | 16 | req := httpClient.R(). 17 | SetResult(&deleteResponse). 18 | SetBody(request) 19 | 20 | res, err := req.Delete(fmt.Sprintf("/v3/secrets/raw/%s", request.SecretKey)) 21 | 22 | if err != nil { 23 | return DeleteSecretV3RawResponse{}, errors.NewRequestError(callDeleteSecretV3RawOperation, err) 24 | } 25 | 26 | if res.IsError() { 27 | return DeleteSecretV3RawResponse{}, errors.NewAPIErrorWithResponse(callDeleteSecretV3RawOperation, res) 28 | } 29 | 30 | return deleteResponse, nil 31 | } 32 | -------------------------------------------------------------------------------- /packages/api/secrets/list_secrets.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | 7 | "github.com/go-resty/resty/v2" 8 | "github.com/hashicorp/golang-lru/v2/expirable" 9 | "github.com/infisical/go-sdk/packages/errors" 10 | "github.com/infisical/go-sdk/packages/util" 11 | ) 12 | 13 | const callListSecretsV3RawOperation = "CallListSecretsV3Raw" 14 | 15 | func CallListSecretsV3(cache *expirable.LRU[string, interface{}], httpClient *resty.Client, request ListSecretsV3RawRequest) (ListSecretsV3RawResponse, error) { 16 | var cacheKey string 17 | 18 | if cache != nil { 19 | reqBytes, err := json.Marshal(request) 20 | if err != nil { 21 | return ListSecretsV3RawResponse{}, err 22 | } 23 | cacheKey = util.ComputeCacheKeyFromBytes(reqBytes, callListSecretsV3RawOperation) 24 | if cached, found := cache.Get(cacheKey); found { 25 | if response, ok := cached.(ListSecretsV3RawResponse); ok { 26 | return response, nil 27 | } 28 | cache.Remove(cacheKey) 29 | } 30 | } 31 | 32 | secretsResponse := ListSecretsV3RawResponse{} 33 | 34 | if request.SecretPath == "" { 35 | request.SecretPath = "/" 36 | } 37 | 38 | res, err := httpClient.R(). 39 | SetResult(&secretsResponse). 40 | SetQueryParams(map[string]string{ 41 | "workspaceId": request.ProjectID, 42 | "workspaceSlug": request.ProjectSlug, 43 | "environment": request.Environment, 44 | "secretPath": request.SecretPath, 45 | "expandSecretReferences": fmt.Sprintf("%t", request.ExpandSecretReferences), 46 | "include_imports": fmt.Sprintf("%t", request.IncludeImports), 47 | "recursive": fmt.Sprintf("%t", request.Recursive), 48 | }).Get("/v3/secrets/raw") 49 | 50 | if err != nil { 51 | return ListSecretsV3RawResponse{}, errors.NewRequestError(callListSecretsV3RawOperation, err) 52 | } 53 | 54 | if res.IsError() { 55 | return ListSecretsV3RawResponse{}, errors.NewAPIErrorWithResponse(callListSecretsV3RawOperation, res) 56 | } 57 | 58 | if cache != nil { 59 | cache.Add(cacheKey, secretsResponse) 60 | } 61 | 62 | return secretsResponse, nil 63 | } 64 | -------------------------------------------------------------------------------- /packages/api/secrets/models.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import "github.com/infisical/go-sdk/packages/models" 4 | 5 | // List secrets 6 | type ListSecretsV3RawRequest struct { 7 | AttachToProcessEnv bool `json:"-"` 8 | 9 | // ProjectId and ProjectSlug are used to fetch secrets from the project. Only one of them is required. 10 | ProjectID string `json:"workspaceId,omitempty"` 11 | ProjectSlug string `json:"workspaceSlug,omitempty"` 12 | Environment string `json:"environment"` 13 | ExpandSecretReferences bool `json:"expandSecretReferences"` 14 | IncludeImports bool `json:"include_imports"` 15 | Recursive bool `json:"recursive"` 16 | SecretPath string `json:"secretPath,omitempty"` 17 | } 18 | 19 | type ListSecretsV3RawResponse struct { 20 | Secrets []models.Secret `json:"secrets"` 21 | Imports []models.SecretImport `json:"imports"` 22 | } 23 | 24 | // Retrieve secret 25 | 26 | type RetrieveSecretV3RawRequest struct { 27 | SecretKey string `json:"secretKey"` 28 | 29 | ProjectSlug string `json:"workspaceSlug,omitempty"` 30 | ProjectID string `json:"workspaceId,omitempty"` 31 | Environment string `json:"environment"` 32 | SecretPath string `json:"secretPath,omitempty"` 33 | Type string `json:"type,omitempty"` 34 | IncludeImports bool `json:"include_imports"` 35 | ExpandSecretReferences bool `json:"expandSecretReferences"` 36 | 37 | Version int `json:"version,omitempty"` 38 | } 39 | 40 | type RetrieveSecretV3RawResponse struct { 41 | Secret models.Secret `json:"secret"` 42 | } 43 | 44 | // Update secret 45 | type UpdateSecretV3RawRequest struct { 46 | SecretKey string `json:"-"` 47 | 48 | ProjectID string `json:"workspaceId"` 49 | Environment string `json:"environment"` 50 | SecretPath string `json:"secretPath,omitempty"` 51 | Type string `json:"type,omitempty"` 52 | 53 | NewSecretValue string `json:"secretValue,omitempty"` 54 | NewSkipMultilineEncoding bool `json:"skipMultilineEncoding,omitempty"` 55 | } 56 | 57 | type UpdateSecretV3RawResponse struct { 58 | Secret models.Secret `json:"secret"` 59 | } 60 | 61 | // Create secret 62 | type CreateSecretV3RawRequest struct { 63 | SecretKey string `json:"-"` 64 | 65 | ProjectID string `json:"workspaceId"` 66 | Environment string `json:"environment"` 67 | SecretPath string `json:"secretPath,omitempty"` 68 | Type string `json:"type,omitempty"` 69 | SecretComment string `json:"secretComment,omitempty"` 70 | SkipMultiLineEncoding bool `json:"skipMultilineEncoding"` 71 | SecretValue string `json:"secretValue"` 72 | } 73 | 74 | type CreateSecretV3RawResponse struct { 75 | Secret models.Secret `json:"secret"` 76 | } 77 | 78 | // Delete secret 79 | type DeleteSecretV3RawRequest struct { 80 | SecretKey string `json:"-"` 81 | 82 | ProjectID string `json:"workspaceId"` 83 | Environment string `json:"environment"` 84 | SecretPath string `json:"secretPath,omitempty"` 85 | Type string `json:"type,omitempty"` 86 | } 87 | 88 | type DeleteSecretV3RawResponse struct { 89 | Secret models.Secret `json:"secret"` 90 | } 91 | 92 | type BatchCreateSecret struct { 93 | SecretKey string `json:"secretKey"` 94 | SecretValue string `json:"secretValue"` 95 | SecretComment string `json:"secretComment,omitempty"` 96 | SkipMultiLineEncoding bool `json:"skipMultilineEncoding,omitempty"` 97 | SecretMetadata []models.SecretMetadata `json:"secretMetadata,omitempty"` 98 | TagIDs []string `json:"tagIds,omitempty"` 99 | } 100 | 101 | type BatchCreateSecretsV3RawRequest struct { 102 | Environment string `json:"environment"` 103 | ProjectID string `json:"workspaceId"` 104 | SecretPath string `json:"secretPath,omitempty"` 105 | Secrets []BatchCreateSecret `json:"secrets"` 106 | } 107 | 108 | type BatchCreateSecretsV3RawResponse struct { 109 | Secrets []models.Secret `json:"secrets"` 110 | } 111 | -------------------------------------------------------------------------------- /packages/api/secrets/retrieve_secret.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "fmt" 7 | 8 | "github.com/go-resty/resty/v2" 9 | "github.com/hashicorp/golang-lru/v2/expirable" 10 | sdkErrors "github.com/infisical/go-sdk/packages/errors" 11 | "github.com/infisical/go-sdk/packages/util" 12 | ) 13 | 14 | const callRetrieveSecretV3RawOperation = "CallRetrieveSecretV3Raw" 15 | 16 | func CallRetrieveSecretV3(cache *expirable.LRU[string, interface{}], httpClient *resty.Client, request RetrieveSecretV3RawRequest) (RetrieveSecretV3RawResponse, error) { 17 | var cacheKey string 18 | 19 | if cache != nil { 20 | reqBytes, err := json.Marshal(request) 21 | if err != nil { 22 | return RetrieveSecretV3RawResponse{}, err 23 | } 24 | cacheKey = util.ComputeCacheKeyFromBytes(reqBytes, callRetrieveSecretV3RawOperation) 25 | if cached, found := cache.Get(cacheKey); found { 26 | if response, ok := cached.(RetrieveSecretV3RawResponse); ok { 27 | return response, nil 28 | } 29 | cache.Remove(cacheKey) 30 | } 31 | } 32 | 33 | retrieveResponse := RetrieveSecretV3RawResponse{} 34 | 35 | if request.Type == "" { 36 | request.Type = "shared" 37 | } 38 | 39 | if request.SecretPath == "" { 40 | request.SecretPath = "/" 41 | } 42 | 43 | queryParams := map[string]string{ 44 | "environment": request.Environment, 45 | "secretPath": request.SecretPath, 46 | "expandSecretReferences": fmt.Sprintf("%t", request.ExpandSecretReferences), 47 | "include_imports": fmt.Sprintf("%t", request.IncludeImports), 48 | "type": request.Type, 49 | } 50 | if request.ProjectID != "" { 51 | queryParams["workspaceId"] = request.ProjectID 52 | } else if request.ProjectSlug != "" { 53 | queryParams["workspaceSlug"] = request.ProjectSlug 54 | } else { 55 | return RetrieveSecretV3RawResponse{}, errors.New("projectId or projectSlug is required") 56 | } 57 | 58 | if request.Version != 0 { 59 | queryParams["version"] = fmt.Sprintf("%d", request.Version) 60 | } 61 | 62 | req := httpClient.R(). 63 | SetResult(&retrieveResponse). 64 | SetQueryParams(queryParams) 65 | 66 | res, err := req.Get(fmt.Sprintf("/v3/secrets/raw/%s", request.SecretKey)) 67 | 68 | if err != nil { 69 | return RetrieveSecretV3RawResponse{}, sdkErrors.NewRequestError(callRetrieveSecretV3RawOperation, err) 70 | } 71 | 72 | if res.IsError() { 73 | return RetrieveSecretV3RawResponse{}, sdkErrors.NewAPIErrorWithResponse(callRetrieveSecretV3RawOperation, res) 74 | } 75 | 76 | if cache != nil { 77 | cache.Add(cacheKey, retrieveResponse) 78 | } 79 | 80 | return retrieveResponse, nil 81 | } 82 | -------------------------------------------------------------------------------- /packages/api/secrets/update_secret.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/go-resty/resty/v2" 7 | "github.com/infisical/go-sdk/packages/errors" 8 | ) 9 | 10 | const callUpdateSecretV3RawOperation = "CallUpdateSecretV3Raw" 11 | 12 | func CallUpdateSecretV3(httpClient *resty.Client, request UpdateSecretV3RawRequest) (UpdateSecretV3RawResponse, error) { 13 | 14 | updateResponse := UpdateSecretV3RawResponse{} 15 | 16 | req := httpClient.R(). 17 | SetResult(&updateResponse). 18 | SetBody(request) 19 | 20 | res, err := req.Patch(fmt.Sprintf("/v3/secrets/raw/%s", request.SecretKey)) 21 | 22 | if err != nil { 23 | return UpdateSecretV3RawResponse{}, errors.NewRequestError(callUpdateSecretV3RawOperation, err) 24 | } 25 | 26 | if res.IsError() { 27 | return UpdateSecretV3RawResponse{}, errors.NewAPIErrorWithResponse(callUpdateSecretV3RawOperation, res) 28 | } 29 | 30 | return updateResponse, nil 31 | } 32 | -------------------------------------------------------------------------------- /packages/api/ssh/add_ssh_host.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | ) 7 | 8 | const callAddSshHostOperation = "CallAddSshHostV1" 9 | 10 | func CallAddSshHostV1(httpClient *resty.Client, body AddSshHostV1Request) (AddSshHostV1Response, error) { 11 | resp := AddSshHostV1Response{} 12 | 13 | res, err := httpClient.R(). 14 | SetBody(body). 15 | SetResult(&resp). 16 | Post("/v1/ssh/hosts") 17 | 18 | if err != nil { 19 | return AddSshHostV1Response{}, errors.NewRequestError(callAddSshHostOperation, err) 20 | } 21 | 22 | if res.IsError() { 23 | return AddSshHostV1Response{}, errors.NewAPIErrorWithResponse(callAddSshHostOperation, res) 24 | } 25 | 26 | return resp, nil 27 | } 28 | -------------------------------------------------------------------------------- /packages/api/ssh/get_ssh_host_host_ca_pk.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | ) 7 | 8 | func GetSshHostHostCaPublicKeyV1(httpClient *resty.Client, sshHostId string) (string, error) { 9 | res, err := httpClient.R(). 10 | Get("/v1/ssh/hosts/" + sshHostId + "/host-ca-public-key") 11 | 12 | if err != nil { 13 | return "", errors.NewRequestError("GetSshHostHostCaPublicKeyV1", err) 14 | } 15 | 16 | if res.IsError() { 17 | return "", errors.NewAPIErrorWithResponse("GetSshHostHostCaPublicKeyV1", res) 18 | } 19 | 20 | return res.String(), nil 21 | } 22 | -------------------------------------------------------------------------------- /packages/api/ssh/get_ssh_host_user_ca_pk.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | ) 7 | 8 | func GetSshHostUserCaPublicKeyV1(httpClient *resty.Client, sshHostId string) (string, error) { 9 | res, err := httpClient.R(). 10 | Get("/v1/ssh/hosts/" + sshHostId + "/user-ca-public-key") 11 | 12 | if err != nil { 13 | return "", errors.NewRequestError("GetSshHostUserCaPublicKeyV1", err) 14 | } 15 | 16 | if res.IsError() { 17 | return "", errors.NewAPIErrorWithResponse("GetSshHostUserCaPublicKeyV1", res) 18 | } 19 | 20 | return res.String(), nil 21 | } 22 | -------------------------------------------------------------------------------- /packages/api/ssh/get_ssh_hosts.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | ) 7 | 8 | const callGetSshHostsOperation = "CallGetSshHostsV1" 9 | 10 | func GetSshHostsV1(httpClient *resty.Client, _ GetSshHostsV1Request) (GetSshHostsV1Response, error) { 11 | var getSshHostsResponse GetSshHostsV1Response 12 | 13 | res, err := httpClient.R(). 14 | SetResult(&getSshHostsResponse). 15 | Get("/v1/ssh/hosts") 16 | 17 | if err != nil { 18 | return nil, errors.NewRequestError(callGetSshHostsOperation, err) 19 | } 20 | 21 | if res.IsError() { 22 | return nil, errors.NewAPIErrorWithResponse(callGetSshHostsOperation, res) 23 | } 24 | 25 | return getSshHostsResponse, nil 26 | } 27 | -------------------------------------------------------------------------------- /packages/api/ssh/issue_ssh_creds.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | ) 7 | 8 | const callIssueSshCredsOperation = "CallIssueSshCredsV1" 9 | 10 | func CallIssueSshCredsV1(httpClient *resty.Client, request IssueSshCredsV1Request) (IssueSshCredsV1Response, error) { 11 | issueSshCredsResponse := IssueSshCredsV1Response{} 12 | 13 | res, err := httpClient.R(). 14 | SetResult(&issueSshCredsResponse). 15 | SetBody(request). 16 | Post("/v1/ssh/certificates/issue") 17 | 18 | if err != nil { 19 | return IssueSshCredsV1Response{}, errors.NewRequestError(callIssueSshCredsOperation, err) 20 | } 21 | 22 | if res.IsError() { 23 | return IssueSshCredsV1Response{}, errors.NewAPIErrorWithResponse(callIssueSshCredsOperation, res) 24 | } 25 | 26 | return issueSshCredsResponse, nil 27 | } 28 | -------------------------------------------------------------------------------- /packages/api/ssh/issue_ssh_host_host_cert.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/go-resty/resty/v2" 7 | "github.com/infisical/go-sdk/packages/errors" 8 | ) 9 | 10 | const callIssueSshHostHostCertOperation = "CallIssueSshHostHostCertV1" 11 | 12 | func CallIssueSshHostHostCertV1(httpClient *resty.Client, sshHostId string, body IssueSshHostHostCertV1Request) (IssueSshHostHostCertV1Response, error) { 13 | resp := IssueSshHostHostCertV1Response{} 14 | 15 | res, err := httpClient.R(). 16 | SetBody(body). 17 | SetResult(&resp). 18 | Post(fmt.Sprintf("/v1/ssh/hosts/%s/issue-host-cert", sshHostId)) 19 | 20 | if err != nil { 21 | return IssueSshHostHostCertV1Response{}, errors.NewRequestError(callIssueSshHostHostCertOperation, err) 22 | } 23 | 24 | if res.IsError() { 25 | return IssueSshHostHostCertV1Response{}, errors.NewAPIErrorWithResponse(callIssueSshHostHostCertOperation, res) 26 | } 27 | 28 | return resp, nil 29 | } 30 | -------------------------------------------------------------------------------- /packages/api/ssh/issue_ssh_host_user_cert.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/go-resty/resty/v2" 7 | "github.com/infisical/go-sdk/packages/errors" 8 | ) 9 | 10 | const callIssueSshHostUserCertOperation = "CallIssueSshHostUserCertV1" 11 | 12 | func CallIssueSshHostUserCertV1(httpClient *resty.Client, sshHostId string, body IssueSshHostUserCertV1Request) (IssueSshHostUserCertV1Response, error) { 13 | resp := IssueSshHostUserCertV1Response{} 14 | 15 | res, err := httpClient.R(). 16 | SetBody(body). 17 | SetResult(&resp). 18 | Post(fmt.Sprintf("/v1/ssh/hosts/%s/issue-user-cert", sshHostId)) 19 | 20 | if err != nil { 21 | return IssueSshHostUserCertV1Response{}, errors.NewRequestError(callIssueSshHostUserCertOperation, err) 22 | } 23 | 24 | if res.IsError() { 25 | return IssueSshHostUserCertV1Response{}, errors.NewAPIErrorWithResponse(callIssueSshHostUserCertOperation, res) 26 | } 27 | 28 | return resp, nil 29 | } 30 | -------------------------------------------------------------------------------- /packages/api/ssh/models.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/infisical/go-sdk/packages/util" 5 | ) 6 | 7 | type SignSshPublicKeyV1Request struct { 8 | CertificateTemplateID string `json:"certificateTemplateId"` 9 | PublicKey string `json:"publicKey"` 10 | CertType util.SshCertType `json:"certType,omitempty"` 11 | Principals []string `json:"principals"` 12 | TTL string `json:"ttl,omitempty"` 13 | KeyID string `json:"keyId,omitempty"` 14 | } 15 | 16 | type SignSshPublicKeyV1Response struct { 17 | SerialNumber string `json:"serialNumber"` 18 | SignedKey string `json:"signedKey"` 19 | } 20 | 21 | type IssueSshCredsV1Request struct { 22 | CertificateTemplateID string `json:"certificateTemplateId"` 23 | KeyAlgorithm util.CertKeyAlgorithm `json:"keyAlgorithm,omitempty"` 24 | CertType util.SshCertType `json:"certType,omitempty"` 25 | Principals []string `json:"principals"` 26 | TTL string `json:"ttl,omitempty"` 27 | KeyID string `json:"keyId,omitempty"` 28 | } 29 | 30 | type IssueSshCredsV1Response struct { 31 | SerialNumber string `json:"serialNumber"` 32 | SignedKey string `json:"signedKey"` 33 | PrivateKey string `json:"privateKey"` 34 | PublicKey string `json:"publicKey"` 35 | KeyAlgorithm util.CertKeyAlgorithm `json:"keyAlgorithm"` 36 | } 37 | 38 | type GetSshHostsV1Request struct{} 39 | 40 | type AllowedPrincipals struct { 41 | Usernames []string `json:"usernames"` 42 | } 43 | 44 | type SshHostLoginMapping struct { 45 | LoginUser string `json:"loginUser"` 46 | AllowedPrincipals AllowedPrincipals `json:"allowedPrincipals"` 47 | } 48 | 49 | type SshHost struct { 50 | ID string `json:"id"` 51 | ProjectID string `json:"projectId"` 52 | Hostname string `json:"hostname"` 53 | Alias string `json:"alias,omitempty"` 54 | UserCertTtl string `json:"userCertTtl"` 55 | HostCertTtl string `json:"hostCertTtl"` 56 | UserSshCaId string `json:"userSshCaId"` 57 | HostSshCaId string `json:"hostSshCaId"` 58 | LoginMappings []SshHostLoginMapping `json:"loginMappings"` 59 | } 60 | 61 | type GetSshHostsV1Response []SshHost 62 | 63 | type IssueSshHostUserCertV1Request struct { 64 | LoginUser string `json:"loginUser"` 65 | } 66 | 67 | type IssueSshHostUserCertV1Response struct { 68 | SerialNumber string `json:"serialNumber"` 69 | SignedKey string `json:"signedKey"` 70 | PrivateKey string `json:"privateKey"` 71 | PublicKey string `json:"publicKey"` 72 | KeyAlgorithm util.CertKeyAlgorithm `json:"keyAlgorithm"` 73 | } 74 | 75 | type IssueSshHostHostCertV1Request struct { 76 | PublicKey string `json:"publicKey"` 77 | } 78 | 79 | type IssueSshHostHostCertV1Response struct { 80 | SerialNumber string `json:"serialNumber"` 81 | SignedKey string `json:"signedKey"` 82 | } 83 | 84 | type AddSshHostV1Request struct { 85 | ProjectID string `json:"projectId"` 86 | Hostname string `json:"hostname"` 87 | Alias string `json:"alias,omitempty"` 88 | UserCertTtl string `json:"userCertTtl,omitempty"` 89 | HostCertTtl string `json:"hostCertTtl,omitempty"` 90 | UserSshCaId string `json:"userSshCaId,omitempty"` 91 | HostSshCaId string `json:"hostSshCaId,omitempty"` 92 | LoginMappings []SshHostLoginMapping `json:"loginMappings,omitempty"` 93 | } 94 | 95 | type AddSshHostV1Response SshHost 96 | -------------------------------------------------------------------------------- /packages/api/ssh/sign_ssh_public_key.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | "github.com/infisical/go-sdk/packages/errors" 6 | ) 7 | 8 | const callSignSshPublicKeyOperation = "CallSignSshPublicKeyV1" 9 | 10 | func CallSignSshPublicKeyV1(httpClient *resty.Client, request SignSshPublicKeyV1Request) (SignSshPublicKeyV1Response, error) { 11 | signSshPublicKeyResponse := SignSshPublicKeyV1Response{} 12 | 13 | res, err := httpClient.R(). 14 | SetResult(&signSshPublicKeyResponse). 15 | SetBody(request). 16 | Post("/v1/ssh/certificates/sign") 17 | 18 | if err != nil { 19 | return SignSshPublicKeyV1Response{}, errors.NewRequestError(callSignSshPublicKeyOperation, err) 20 | } 21 | 22 | if res.IsError() { 23 | return SignSshPublicKeyV1Response{}, errors.NewAPIErrorWithResponse(callSignSshPublicKeyOperation, res) 24 | } 25 | 26 | return signSshPublicKeyResponse, nil 27 | } 28 | -------------------------------------------------------------------------------- /packages/errors/api.go: -------------------------------------------------------------------------------- 1 | package errors 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/go-resty/resty/v2" 7 | "github.com/infisical/go-sdk/packages/util" 8 | ) 9 | 10 | // APIError represents an error response from the API 11 | type APIError struct { 12 | Operation string `json:"operation"` 13 | Method string `json:"method"` 14 | URL string `json:"url"` 15 | StatusCode int `json:"statusCode"` 16 | ErrorMessage string `json:"message,omitempty"` 17 | ReqId string `json:"reqId,omitempty"` 18 | } 19 | 20 | func (e *APIError) Error() string { 21 | msg := fmt.Sprintf( 22 | "APIError: %s unsuccessful response [%v %v] [status-code=%v] [reqId=%v]", 23 | e.Operation, 24 | e.Method, 25 | e.URL, 26 | e.StatusCode, 27 | e.ReqId, 28 | ) 29 | 30 | if e.ErrorMessage != "" { 31 | return fmt.Sprintf("%s [message=\"%s\"]", msg, e.ErrorMessage) 32 | 33 | } 34 | 35 | return msg 36 | } 37 | 38 | func NewAPIError(operation string, res *resty.Response) error { 39 | return &APIError{ 40 | Operation: operation, 41 | Method: res.Request.Method, 42 | URL: res.Request.URL, 43 | StatusCode: res.StatusCode(), 44 | } 45 | } 46 | 47 | func NewAPIErrorWithResponse(operation string, res *resty.Response) error { 48 | errorMessage := util.TryParseErrorBody(res) 49 | reqId := util.TryExtractReqId(res) 50 | 51 | return &APIError{ 52 | Operation: operation, 53 | Method: res.Request.Method, 54 | URL: res.Request.URL, 55 | StatusCode: res.StatusCode(), 56 | ErrorMessage: errorMessage, 57 | ReqId: reqId, 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /packages/errors/request.go: -------------------------------------------------------------------------------- 1 | package errors 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // RequestError represents an error that occurred during an API request 8 | type RequestError struct { 9 | Operation string `json:"operation"` 10 | error error `json:"-"` 11 | } 12 | 13 | func (e *RequestError) Error() string { 14 | return fmt.Sprintf("%s: unable to complete api request [err=%s]", e.Operation, e.error) 15 | } 16 | 17 | func NewRequestError(operation string, err error) error { 18 | return &RequestError{ 19 | Operation: operation, 20 | error: err, 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/models/auth.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type TokenType string 4 | 5 | const ( 6 | BEARER_TOKEN_TYPE TokenType = "Bearer" 7 | ) 8 | 9 | type UniversalAuthCredential struct { 10 | ClientID string 11 | ClientSecret string 12 | } 13 | 14 | type AccessTokenCredential struct { 15 | AccessToken string 16 | } 17 | 18 | type GCPIDTokenCredential struct { 19 | IdentityID string 20 | } 21 | 22 | type GCPIAMCredential struct { 23 | IdentityID string 24 | ServiceAccountKeyFilePath string 25 | } 26 | 27 | type AWSIAMCredential struct { 28 | IdentityID string 29 | } 30 | 31 | type KubernetesCredential struct { 32 | IdentityID string 33 | ServiceAccountToken string 34 | } 35 | 36 | type AzureCredential struct { 37 | IdentityID string 38 | Resource string 39 | } 40 | 41 | type OIDCCredential struct { 42 | IdentityID string 43 | JWT string 44 | } 45 | 46 | type JWTCredential struct { 47 | IdentityID string 48 | JWT string 49 | } 50 | -------------------------------------------------------------------------------- /packages/models/dynamic_secrets.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type DynamicSecret struct { 6 | Id string `json:"id"` 7 | Name string `json:"name"` 8 | Type string `json:"type"` 9 | Version int `json:"number"` 10 | DefaultTTL string `json:"defaultTTL"` 11 | MaxTTL string `json:"maxTTL"` 12 | FolderID string `json:"folderId"` 13 | Status string `json:"status"` 14 | StatusDetails string `json:"statusDetails"` 15 | CreatedAt time.Time `json:"createdAt"` 16 | UpdatedAt time.Time `json:"updatedAt"` 17 | } 18 | 19 | type DynamicSecretLease struct { 20 | Id string `json:"id"` 21 | Type string `json:"type"` 22 | Version int `json:"number"` 23 | ExternalEntityId string `json:"externalEntityId"` 24 | ExpireAt time.Time `json:"expireAt"` 25 | Status string `json:"status"` 26 | DynamicSecretId string `json:"dynamicSecretId"` 27 | StatusDetails string `json:"statusDetails"` 28 | CreatedAt time.Time `json:"createdAt"` 29 | UpdatedAt time.Time `json:"updatedAt"` 30 | } 31 | 32 | type DynamicSecretLeaseWithDynamicSecret struct { 33 | Id string `json:"id"` 34 | Type string `json:"type"` 35 | Version int `json:"number"` 36 | ExternalEntityId string `json:"externalEntityId"` 37 | ExpireAt time.Time `json:"expireAt"` 38 | Status string `json:"status"` 39 | DynamicSecretId string `json:"dynamicSecretId"` 40 | StatusDetails string `json:"statusDetails"` 41 | CreatedAt time.Time `json:"createdAt"` 42 | UpdatedAt time.Time `json:"updatedAt"` 43 | DynamicSecret DynamicSecret `json:"dynamicSecret"` 44 | } 45 | -------------------------------------------------------------------------------- /packages/models/folders.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type Folder struct { 6 | ID string `json:"id"` 7 | Name string `json:"name"` 8 | Version int `json:"version"` 9 | CreatedAt time.Time `json:"createdAt"` 10 | UpdatedAt time.Time `json:"updatedAt"` 11 | EnvironmentID string `json:"envId"` 12 | ParentID string `json:"parentId"` 13 | IsReserved bool `json:"isReserved"` 14 | } 15 | -------------------------------------------------------------------------------- /packages/models/secrets.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type SecretMetadata struct { 4 | Key string `json:"key"` 5 | Value string `json:"value"` 6 | } 7 | 8 | type Secret struct { 9 | ID string `json:"id"` 10 | Workspace string `json:"workspace"` 11 | Environment string `json:"environment"` 12 | Version int `json:"version"` 13 | Type string `json:"type"` 14 | SecretKey string `json:"secretKey"` 15 | SecretValue string `json:"secretValue"` 16 | SecretComment string `json:"secretComment"` 17 | SecretPath string `json:"secretPath,omitempty"` 18 | SecretMetadata []SecretMetadata `json:"secretMetadata"` 19 | } 20 | 21 | type SecretImport struct { 22 | SecretPath string `json:"secretPath"` 23 | Environment string `json:"environment"` 24 | FolderID string `json:"folderId"` 25 | Secrets []Secret `json:"secrets"` 26 | } 27 | -------------------------------------------------------------------------------- /packages/util/auth.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "net/url" 8 | "os" 9 | "time" 10 | 11 | credentials "cloud.google.com/go/iam/credentials/apiv1" 12 | "cloud.google.com/go/iam/credentials/apiv1/credentialspb" 13 | "github.com/aws/aws-sdk-go-v2/aws" 14 | "github.com/aws/aws-sdk-go-v2/config" 15 | "github.com/go-resty/resty/v2" 16 | "google.golang.org/api/option" 17 | ) 18 | 19 | func GetKubernetesServiceAccountToken(serviceAccountTokenPath string) (string, error) { 20 | 21 | if serviceAccountTokenPath == "" { 22 | serviceAccountTokenPath = DEFAULT_KUBERNETES_SERVICE_ACCOUNT_TOKEN_PATH 23 | } 24 | 25 | token, err := os.ReadFile(serviceAccountTokenPath) 26 | 27 | if err != nil { 28 | return "", err 29 | } 30 | 31 | return string(token), nil 32 | 33 | } 34 | 35 | func buildAzureMetadataServiceURL(resource string) string { 36 | if resource != "" { 37 | return AZURE_METADATA_SERVICE_URL + url.PathEscape(resource) 38 | } 39 | return AZURE_METADATA_SERVICE_URL + AZURE_DEFAULT_RESOURCE 40 | } 41 | 42 | func GetAzureMetadataToken(httpClient *resty.Client, customResource string) (string, error) { 43 | 44 | type AzureMetadataResponse struct { 45 | AccessToken string `json:"access_token"` 46 | } 47 | 48 | metadataResponse := AzureMetadataResponse{} 49 | 50 | response, err := httpClient.R(). 51 | SetResult(&metadataResponse). 52 | SetHeader("Metadata", "true"). 53 | SetHeader("Accept", "application/json"). 54 | Get(buildAzureMetadataServiceURL(customResource)) 55 | 56 | if err != nil { 57 | return "", err 58 | } 59 | 60 | if response.IsError() { 61 | return "", fmt.Errorf("GetAzureMetadataToken: Unsuccessful response [%v %v] [status-code=%v] [Error: %s]", response.Request.Method, response.Request.URL, response.StatusCode(), TryParseErrorBody(response)) 62 | } 63 | 64 | return metadataResponse.AccessToken, nil 65 | } 66 | 67 | func GetGCPMetadataToken(httpClient *resty.Client, identityID string) (string, error) { 68 | 69 | res, err := httpClient.R(). 70 | SetHeader("Metadata-Flavor", "Google"). 71 | Get(fmt.Sprintf("http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience=%s&format=full", identityID)) 72 | 73 | if err != nil { 74 | return "", err 75 | } 76 | 77 | if res.IsError() { 78 | return "", fmt.Errorf("GetGCPMetadataToken: Unsuccessful response [%v %v] [status-code=%v] [Error: %s]", res.Request.Method, res.Request.URL, res.StatusCode(), TryParseErrorBody(res)) 79 | } 80 | 81 | return res.String(), nil 82 | 83 | } 84 | 85 | func GetAwsEC2IdentityDocumentRegion(timeout int) (string, error) { 86 | 87 | type AwsIdentityDocument struct { 88 | Region string `json:"region"` 89 | } 90 | 91 | httpClient := resty.New().SetTimeout(time.Duration(timeout) * time.Millisecond) 92 | 93 | res, err := httpClient.R(). 94 | SetHeader("X-aws-ec2-metadata-token-ttl-seconds", "21600"). 95 | Put(AWS_EC2_METADATA_TOKEN_URL) 96 | 97 | if err != nil { 98 | return "", err 99 | } 100 | 101 | if res.IsError() { 102 | return "", fmt.Errorf("GetAwsEC2IdentityDocumentRegion: Unsuccessful response [%v %v] [status-code=%v] [Error: %s]", res.Request.Method, res.Request.URL, res.StatusCode(), TryParseErrorBody(res)) 103 | } 104 | 105 | metadataToken := res.String() 106 | 107 | res, err = httpClient.R(). 108 | SetHeader("X-aws-ec2-metadata-token", metadataToken). 109 | SetHeader("Accept", "application/json"). 110 | Get(AWS_EC2_INSTANCE_IDENTITY_DOCUMENT_URL) 111 | 112 | if err != nil { 113 | return "", err 114 | } 115 | 116 | if res.IsError() { 117 | return "", fmt.Errorf("GetAwsEC2IdentityDocumentRegion: Unsuccessful response [%v %v] [status-code=%v] [Error: %s]", res.Request.Method, res.Request.URL, res.StatusCode(), TryParseErrorBody(res)) 118 | } 119 | 120 | // For some reason using .SetResult(&AwsIdentityDocument{}) doesn't work and just results in an empty object. This works though.. 121 | var identityDocument AwsIdentityDocument 122 | err = json.Unmarshal(res.Body(), &identityDocument) 123 | if err != nil { 124 | return "", err 125 | } 126 | 127 | return identityDocument.Region, nil 128 | 129 | } 130 | 131 | func GetGCPIamServiceAccountToken(identityID string, serviceAccountKeyPath string) (string, error) { 132 | 133 | type JwtPayload struct { 134 | Sub string `json:"sub"` 135 | Aud string `json:"aud"` 136 | } 137 | 138 | ctx := context.Background() 139 | 140 | serviceAccountKey, err := os.ReadFile(serviceAccountKeyPath) 141 | if err != nil { 142 | return "", err 143 | } 144 | 145 | var creds map[string]string 146 | if err := json.Unmarshal(serviceAccountKey, &creds); err != nil { 147 | return "", fmt.Errorf("failed to unmarshal service account key: %v", err) 148 | } 149 | 150 | clientEmail := creds["client_email"] 151 | if clientEmail == "" { 152 | return "", fmt.Errorf("client email not found in service account key") 153 | } 154 | 155 | payload := JwtPayload{ 156 | Sub: clientEmail, 157 | Aud: identityID, 158 | } 159 | 160 | payloadJSON, err := json.Marshal(payload) 161 | if err != nil { 162 | return "", fmt.Errorf("failed to marshal JWT payload: %v", err) 163 | } 164 | 165 | iamCredentialsClient, err := credentials.NewIamCredentialsClient(ctx, option.WithCredentialsFile(serviceAccountKeyPath)) 166 | if err != nil { 167 | return "", fmt.Errorf("failed to create IAM credentials client: %v", err) 168 | } 169 | 170 | defer iamCredentialsClient.Close() 171 | 172 | signJwtRequest := &credentialspb.SignJwtRequest{ 173 | Name: fmt.Sprintf("projects/-/serviceAccounts/%s", clientEmail), 174 | Payload: string(payloadJSON), 175 | } 176 | 177 | resp, err := iamCredentialsClient.SignJwt(ctx, signJwtRequest) 178 | if err != nil { 179 | return "", fmt.Errorf("failed to sign JWT: %v. Ensure the IAM Service Account Credentials API is enabled", err) 180 | } 181 | 182 | signedJwt := resp.SignedJwt 183 | if signedJwt == "" { 184 | return "", fmt.Errorf("failed to sign JWT: signedJwt is empty") 185 | } 186 | 187 | return signedJwt, nil 188 | 189 | } 190 | 191 | func GetAwsRegion() (string, error) { 192 | // in Lambda environments, the region is available in the AWS_REGION environment variable 193 | region := os.Getenv("AWS_REGION") 194 | 195 | if region != "" { 196 | return region, nil 197 | } 198 | 199 | // in EC2 environments, the region is available in the identity doc 200 | 201 | region, err := GetAwsEC2IdentityDocumentRegion(5000) 202 | 203 | if err != nil { 204 | return "", err 205 | } 206 | 207 | return region, nil 208 | 209 | } 210 | 211 | func RetrieveAwsCredentials() (credentials aws.Credentials, region string, err error) { 212 | presetAwsCfg, err := config.LoadDefaultConfig(context.TODO()) 213 | 214 | if err == nil && presetAwsCfg.Region != "" { 215 | creds, err := presetAwsCfg.Credentials.Retrieve(context.TODO()) 216 | if err == nil { 217 | return creds, presetAwsCfg.Region, nil 218 | } 219 | } 220 | 221 | awsRegion, err := GetAwsRegion() 222 | if err != nil { 223 | return aws.Credentials{}, "", err 224 | } 225 | 226 | awsCfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion(awsRegion)) 227 | if err != nil { 228 | return aws.Credentials{}, "", fmt.Errorf("unable to load SDK config, %v", err) 229 | } 230 | 231 | creds, err := awsCfg.Credentials.Retrieve(context.TODO()) 232 | if err != nil { 233 | return aws.Credentials{}, "", fmt.Errorf("error retrieving credentials: %v", err) 234 | } 235 | 236 | return creds, awsRegion, nil 237 | } 238 | -------------------------------------------------------------------------------- /packages/util/constants.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | ) 7 | 8 | // Auth related: 9 | const ( 10 | 11 | // Universal auth: 12 | INFISICAL_UNIVERSAL_AUTH_CLIENT_ID_ENV_NAME = "INFISICAL_UNIVERSAL_AUTH_CLIENT_ID" 13 | INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET_ENV_NAME = "INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET" 14 | 15 | // GCP auth: 16 | INFISICAL_GCP_AUTH_IDENTITY_ID_ENV_NAME = "INFISICAL_GCP_AUTH_IDENTITY_ID" 17 | INFISICAL_GCP_IAM_SERVICE_ACCOUNT_KEY_FILE_PATH_ENV_NAME = "INFISICAL_GCP_IAM_SERVICE_ACCOUNT_KEY_FILE_PATH" 18 | 19 | // AWS auth: 20 | INFISICAL_AWS_IAM_AUTH_IDENTITY_ID_ENV_NAME = "INFISICAL_AWS_IAM_AUTH_IDENTITY_ID" 21 | 22 | // Azure auth: 23 | INFISICAL_AZURE_AUTH_IDENTITY_ID_ENV_NAME = "INFISICAL_AZURE_AUTH_IDENTITY_ID" 24 | 25 | // Kubernetes auth: 26 | INFISICAL_KUBERNETES_IDENTITY_ID_ENV_NAME = "INFISICAL_KUBERNETES_IDENTITY_ID" 27 | INFISICAL_KUBERNETES_SERVICE_ACCOUNT_TOKEN_PATH_ENV_NAME = "INFISICAL_KUBERNETES_SERVICE_ACCOUNT_TOKEN_PATH" 28 | 29 | // OIDC auth: 30 | INFISICAL_OIDC_AUTH_IDENTITY_ID_ENV_NAME = "INFISICAL_OIDC_AUTH_IDENTITY_ID" 31 | 32 | // Access token: 33 | INFISICAL_ACCESS_TOKEN_ENV_NAME = "INFISICAL_ACCESS_TOKEN" 34 | 35 | // AWS metadata service: 36 | AWS_EC2_METADATA_TOKEN_URL = "http://169.254.169.254/latest/api/token" 37 | AWS_EC2_INSTANCE_IDENTITY_DOCUMENT_URL = "http://169.254.169.254/latest/dynamic/instance-identity/document" 38 | 39 | // Azure metadata service: 40 | AZURE_METADATA_SERVICE_URL = "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=" // End of the URL needs to be appended with the resource 41 | AZURE_DEFAULT_RESOURCE = "https%3A%2F%2Fmanagement.azure.com/" 42 | ) 43 | 44 | type AuthMethod string 45 | 46 | const ( 47 | ACCESS_TOKEN AuthMethod = "ACCESS_TOKEN" 48 | UNIVERSAL_AUTH AuthMethod = "UNIVERSAL_AUTH" 49 | GCP_ID_TOKEN AuthMethod = "GCP_ID_TOKEN" 50 | GCP_IAM AuthMethod = "GCP_IAM" 51 | AWS_IAM AuthMethod = "AWS_IAM" 52 | KUBERNETES AuthMethod = "KUBERNETES" 53 | AZURE AuthMethod = "AZURE" 54 | OIDC_AUTH AuthMethod = "OIDC_AUTH" 55 | JWT_AUTH AuthMethod = "JWT_AUTH" 56 | ) 57 | 58 | // SSH related: 59 | type CertKeyAlgorithm string 60 | 61 | const ( 62 | RSA2048 CertKeyAlgorithm = "RSA_2048" 63 | RSA4096 CertKeyAlgorithm = "RSA_4096" 64 | ECDSAP256 CertKeyAlgorithm = "EC_prime256v1" 65 | ECDSAP384 CertKeyAlgorithm = "EC_secp384r1" 66 | ) 67 | 68 | type SshCertType string 69 | 70 | const ( 71 | UserCert SshCertType = "user" 72 | HostCert SshCertType = "host" 73 | ) 74 | 75 | // General: 76 | const ( 77 | DEFAULT_INFISICAL_API_URL = "https://app.infisical.com/api" 78 | DEFAULT_KUBERNETES_SERVICE_ACCOUNT_TOKEN_PATH = "/var/run/secrets/kubernetes.io/serviceaccount/token" 79 | ) 80 | 81 | var ErrContextCanceled = errors.New("context canceled") 82 | var ErrContextDeadlineExceeded error = context.DeadlineExceeded 83 | -------------------------------------------------------------------------------- /packages/util/helper.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "context" 5 | "crypto/sha256" 6 | "encoding/hex" 7 | "encoding/json" 8 | "fmt" 9 | "os" 10 | "sort" 11 | "strings" 12 | "time" 13 | 14 | "github.com/go-resty/resty/v2" 15 | "github.com/infisical/go-sdk/packages/models" 16 | ) 17 | 18 | func AppendAPIEndpoint(siteUrl string) string { 19 | // Ensure the address does not already end with "/api" 20 | if strings.HasSuffix(siteUrl, "/api") { 21 | return siteUrl 22 | } 23 | 24 | // Check if the address ends with a slash and append accordingly 25 | if siteUrl[len(siteUrl)-1] == '/' { 26 | return siteUrl + "api" 27 | } 28 | return siteUrl + "/api" 29 | } 30 | 31 | func PrintWarning(message string) { 32 | fmt.Fprintf(os.Stderr, "[Infisical] Warning: %v \n", message) 33 | } 34 | 35 | func EnsureUniqueSecretsByKey(secrets *[]models.Secret) { 36 | secretMap := make(map[string]models.Secret) 37 | 38 | // Move secrets to a map to ensure uniqueness 39 | for _, secret := range *secrets { 40 | secretMap[secret.SecretKey] = secret // Maps will overwrite existing entry with the same key 41 | } 42 | 43 | // Clear the slice 44 | *secrets = (*secrets)[:0] 45 | 46 | // Refill the slice from the map 47 | for _, secret := range secretMap { 48 | *secrets = append(*secrets, secret) 49 | } 50 | } 51 | 52 | // containsSecret checks if the given key exists in the slice of secrets 53 | func ContainsSecret(secrets []models.Secret, key string) bool { 54 | for _, secret := range secrets { 55 | if secret.SecretKey == key { 56 | return true 57 | } 58 | } 59 | return false 60 | } 61 | 62 | // Helper function to sort the secrets by key so we can create a consistent output 63 | func SortSecretsByKeys(secrets []models.Secret) []models.Secret { 64 | sort.Slice(secrets, func(i, j int) bool { 65 | return secrets[i].SecretKey < secrets[j].SecretKey 66 | }) 67 | return secrets 68 | } 69 | 70 | /* 71 | If the status code is 400, there will most likely always be a body. 72 | The body is a json object with a message key. we need to try to parse it, but if it fails, we can just return an empty string. 73 | But if the status code is 500, there may not be a body. if there is, it will be a json object with a message key. we need to try to parse it, but if it fails, we can just return an empty string 74 | */ 75 | func TryParseErrorBody(res *resty.Response) string { 76 | if res == nil || !res.IsError() { 77 | return "" 78 | } 79 | 80 | body := res.String() 81 | if body == "" { 82 | return "" 83 | } 84 | 85 | type ErrorResponse struct { 86 | Message string `json:"message"` 87 | ReqId string `json:"reqId"` 88 | } 89 | 90 | // stringify zod body entirely 91 | if res.StatusCode() == 422 { 92 | return body 93 | } 94 | 95 | // now we have a string, we need to try to parse it as json 96 | var errorResponse ErrorResponse 97 | err := json.Unmarshal([]byte(body), &errorResponse) 98 | 99 | if err != nil { 100 | return "" 101 | } 102 | 103 | return errorResponse.Message 104 | } 105 | 106 | func TryExtractReqId(res *resty.Response) string { 107 | if res == nil || !res.IsError() { 108 | return "" 109 | } 110 | 111 | type ErrorResponse struct { 112 | ReqId string `json:"reqId"` 113 | } 114 | 115 | var errorResponse ErrorResponse 116 | 117 | err := json.Unmarshal([]byte(res.String()), &errorResponse) 118 | 119 | if err != nil { 120 | return "" 121 | } 122 | 123 | return errorResponse.ReqId 124 | } 125 | 126 | func SleepWithContext(ctx context.Context, duration time.Duration) error { 127 | select { 128 | case <-ctx.Done(): 129 | return ctx.Err() 130 | case <-time.After(duration): 131 | return nil 132 | } 133 | } 134 | 135 | func ComputeCacheKeyFromBytes(bytes []byte, feature string) string { 136 | key := sha256.Sum256(bytes) 137 | return fmt.Sprintf("%s-%s", feature, hex.EncodeToString(key[:])) 138 | } 139 | -------------------------------------------------------------------------------- /resources/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /secrets.go: -------------------------------------------------------------------------------- 1 | package infisical 2 | 3 | import ( 4 | "os" 5 | 6 | api "github.com/infisical/go-sdk/packages/api/secrets" 7 | "github.com/infisical/go-sdk/packages/models" 8 | "github.com/infisical/go-sdk/packages/util" 9 | ) 10 | 11 | type ListSecretsOptions = api.ListSecretsV3RawRequest 12 | type RetrieveSecretOptions = api.RetrieveSecretV3RawRequest 13 | type UpdateSecretOptions = api.UpdateSecretV3RawRequest 14 | type CreateSecretOptions = api.CreateSecretV3RawRequest 15 | type DeleteSecretOptions = api.DeleteSecretV3RawRequest 16 | 17 | type BatchCreateSecret = api.BatchCreateSecret 18 | type SecretMetadata = models.SecretMetadata 19 | 20 | type BatchCreateSecretsOptions = api.BatchCreateSecretsV3RawRequest 21 | 22 | type BatchSecretsInterface interface { 23 | Create(options BatchCreateSecretsOptions) ([]models.Secret, error) 24 | } 25 | 26 | type SecretsInterface interface { 27 | List(options ListSecretsOptions) ([]models.Secret, error) 28 | Retrieve(options RetrieveSecretOptions) (models.Secret, error) 29 | Update(options UpdateSecretOptions) (models.Secret, error) 30 | Create(options CreateSecretOptions) (models.Secret, error) 31 | Delete(options DeleteSecretOptions) (models.Secret, error) 32 | Batch() BatchSecretsInterface 33 | } 34 | 35 | type Secrets struct { 36 | client *InfisicalClient 37 | } 38 | 39 | type BatchSecrets struct { 40 | client *InfisicalClient 41 | } 42 | 43 | func (s *Secrets) List(options ListSecretsOptions) ([]models.Secret, error) { 44 | res, err := api.CallListSecretsV3(s.client.cache, s.client.httpClient, options) 45 | 46 | if err != nil { 47 | return nil, err 48 | } 49 | 50 | if options.Recursive { 51 | util.EnsureUniqueSecretsByKey(&res.Secrets) 52 | } 53 | 54 | secrets := append([]models.Secret(nil), res.Secrets...) // Clone main secrets slice, we will modify this if imports are enabled 55 | if options.IncludeImports { 56 | 57 | // Append secrets from imports 58 | for _, importBlock := range res.Imports { 59 | for _, importSecret := range importBlock.Secrets { 60 | // Only append the secret if it is not already in the list, imports take precedence 61 | if !util.ContainsSecret(secrets, importSecret.SecretKey) { 62 | secrets = append(secrets, importSecret) 63 | } 64 | } 65 | } 66 | } 67 | 68 | if options.AttachToProcessEnv { 69 | for _, secret := range secrets { 70 | // Only set the environment variable if it is not already set 71 | if os.Getenv(secret.SecretKey) == "" { 72 | os.Setenv(secret.SecretKey, secret.SecretValue) 73 | } 74 | } 75 | 76 | } 77 | 78 | return util.SortSecretsByKeys(secrets), nil 79 | } 80 | 81 | func (s *Secrets) Retrieve(options RetrieveSecretOptions) (models.Secret, error) { 82 | res, err := api.CallRetrieveSecretV3(s.client.cache, s.client.httpClient, options) 83 | 84 | if err != nil { 85 | return models.Secret{}, err 86 | } 87 | 88 | return res.Secret, nil 89 | } 90 | 91 | func (s *Secrets) Update(options UpdateSecretOptions) (models.Secret, error) { 92 | res, err := api.CallUpdateSecretV3(s.client.httpClient, options) 93 | 94 | if err != nil { 95 | return models.Secret{}, err 96 | } 97 | 98 | return res.Secret, nil 99 | } 100 | 101 | func (s *Secrets) Create(options CreateSecretOptions) (models.Secret, error) { 102 | res, err := api.CallCreateSecretV3(s.client.httpClient, options) 103 | 104 | if err != nil { 105 | return models.Secret{}, err 106 | } 107 | 108 | return res.Secret, nil 109 | } 110 | 111 | func (s *Secrets) Delete(options DeleteSecretOptions) (models.Secret, error) { 112 | res, err := api.CallDeleteSecretV3(s.client.httpClient, options) 113 | 114 | if err != nil { 115 | return models.Secret{}, err 116 | } 117 | 118 | return res.Secret, nil 119 | } 120 | 121 | // Batch operations 122 | 123 | func (bs *BatchSecrets) Create(options BatchCreateSecretsOptions) ([]models.Secret, error) { 124 | res, err := api.CallBatchCreateSecretV3(bs.client.httpClient, options) 125 | 126 | if err != nil { 127 | return nil, err 128 | } 129 | 130 | return res.Secrets, nil 131 | } 132 | 133 | func (s *Secrets) Batch() BatchSecretsInterface { 134 | return &BatchSecrets{client: s.client} 135 | } 136 | 137 | func NewSecrets(client *InfisicalClient) SecretsInterface { 138 | return &Secrets{client: client} 139 | } 140 | -------------------------------------------------------------------------------- /ssh.go: -------------------------------------------------------------------------------- 1 | package infisical 2 | 3 | import ( 4 | api "github.com/infisical/go-sdk/packages/api/ssh" 5 | ) 6 | 7 | type SignSshPublicKeyOptions = api.SignSshPublicKeyV1Request 8 | type IssueSshCredsOptions = api.IssueSshCredsV1Request 9 | type GetSshHostsOptions = api.GetSshHostsV1Request 10 | type IssueSshHostUserCertOptions = api.IssueSshHostUserCertV1Request 11 | type IssueSshHostHostCertOptions = api.IssueSshHostHostCertV1Request 12 | type AddSshHostOptions = api.AddSshHostV1Request 13 | 14 | type SshInterface interface { 15 | SignKey(options SignSshPublicKeyOptions) (api.SignSshPublicKeyV1Response, error) 16 | IssueCredentials(options IssueSshCredsOptions) (api.IssueSshCredsV1Response, error) 17 | GetSshHosts(options GetSshHostsOptions) (api.GetSshHostsV1Response, error) 18 | GetSshHostUserCaPublicKey(sshHostId string) (string, error) 19 | GetSshHostHostCaPublicKey(sshHostId string) (string, error) 20 | IssueSshHostUserCert(sshHostId string, options IssueSshHostUserCertOptions) (api.IssueSshHostUserCertV1Response, error) 21 | IssueSshHostHostCert(sshHostId string, options IssueSshHostHostCertOptions) (api.IssueSshHostHostCertV1Response, error) 22 | AddSshHost(options AddSshHostOptions) (api.AddSshHostV1Response, error) 23 | } 24 | 25 | type Ssh struct { 26 | client *InfisicalClient 27 | } 28 | 29 | func (f *Ssh) SignKey(options SignSshPublicKeyOptions) (api.SignSshPublicKeyV1Response, error) { 30 | res, err := api.CallSignSshPublicKeyV1(f.client.httpClient, options) 31 | 32 | if err != nil { 33 | return api.SignSshPublicKeyV1Response{}, err 34 | } 35 | 36 | return res, nil 37 | } 38 | 39 | func (f *Ssh) IssueCredentials(options IssueSshCredsOptions) (api.IssueSshCredsV1Response, error) { 40 | res, err := api.CallIssueSshCredsV1(f.client.httpClient, options) 41 | 42 | if err != nil { 43 | return api.IssueSshCredsV1Response{}, err 44 | } 45 | 46 | return res, nil 47 | } 48 | 49 | func (f *Ssh) GetSshHosts(options GetSshHostsOptions) (api.GetSshHostsV1Response, error) { 50 | res, err := api.GetSshHostsV1(f.client.httpClient, options) 51 | 52 | if err != nil { 53 | return api.GetSshHostsV1Response{}, err 54 | } 55 | 56 | return res, nil 57 | } 58 | 59 | func (f *Ssh) GetSshHostUserCaPublicKey(sshHostId string) (string, error) { 60 | res, err := api.GetSshHostUserCaPublicKeyV1(f.client.httpClient, sshHostId) 61 | 62 | if err != nil { 63 | return "", err 64 | } 65 | 66 | return res, nil 67 | } 68 | 69 | func (f *Ssh) GetSshHostHostCaPublicKey(sshHostId string) (string, error) { 70 | res, err := api.GetSshHostHostCaPublicKeyV1(f.client.httpClient, sshHostId) 71 | 72 | if err != nil { 73 | return "", err 74 | } 75 | 76 | return res, nil 77 | } 78 | 79 | func (f *Ssh) IssueSshHostUserCert(sshHostId string, options IssueSshHostUserCertOptions) (api.IssueSshHostUserCertV1Response, error) { 80 | res, err := api.CallIssueSshHostUserCertV1(f.client.httpClient, sshHostId, options) 81 | if err != nil { 82 | return api.IssueSshHostUserCertV1Response{}, err 83 | } 84 | return res, nil 85 | } 86 | 87 | func (f *Ssh) IssueSshHostHostCert(sshHostId string, options IssueSshHostHostCertOptions) (api.IssueSshHostHostCertV1Response, error) { 88 | res, err := api.CallIssueSshHostHostCertV1(f.client.httpClient, sshHostId, options) 89 | if err != nil { 90 | return api.IssueSshHostHostCertV1Response{}, err 91 | } 92 | return res, nil 93 | } 94 | 95 | func (f *Ssh) AddSshHost(options AddSshHostOptions) (api.AddSshHostV1Response, error) { 96 | res, err := api.CallAddSshHostV1(f.client.httpClient, options) 97 | if err != nil { 98 | return api.AddSshHostV1Response{}, err 99 | } 100 | return res, nil 101 | } 102 | 103 | func NewSsh(client *InfisicalClient) SshInterface { 104 | return &Ssh{client: client} 105 | } 106 | -------------------------------------------------------------------------------- /test/aws_auth_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "testing" 7 | 8 | infisical "github.com/infisical/go-sdk" 9 | ) 10 | 11 | func TestAWSAuthLogin(t *testing.T) { 12 | 13 | client := infisical.NewInfisicalClient(context.Background(), infisical.Config{ 14 | SiteUrl: "https://c61b724baab4.ngrok.app", 15 | }) 16 | 17 | accessToken, err := client.Auth().AwsIamAuthLogin("e2cddb75-a0e0-4c89-bfc0-4d536599f725") // test ID 18 | 19 | if err != nil { 20 | panic(err) 21 | } 22 | 23 | fmt.Println("Obtained access token: ", accessToken) 24 | } 25 | -------------------------------------------------------------------------------- /test/kubernetes_auth_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | // import ( 4 | // "testing" 5 | 6 | // infisical "github.com/infisical/go-sdk" 7 | // ) 8 | 9 | // func TestKubernetesAuthLogin(t *testing.T) { 10 | 11 | // t.Skip("Skipping Kubernetes Auth test -- requires running in a Kubernetes cluster") 12 | 13 | // client, err := infisical.NewInfisicalClient(infisical.Config{ 14 | // SiteUrl: "http://localhost:8080", 15 | // Auth: infisical.Authentication{ 16 | // Kubernetes: infisical.KubernetesAuth{ 17 | // IdentityID: "K8_MACHINE_IDENTITY_ID", 18 | // ServiceAccountTokenPath: "/var/run/secrets/kubernetes.io/serviceaccount/token", // Optional 19 | // }, 20 | // }, 21 | // }) 22 | 23 | // // token1, err := client1.auth.kubernetesLogin(...) 24 | // // token2, err := client2.auth.kubernetesLogin(...) 25 | 26 | // // handle err 27 | 28 | // // client.auth.setToken(token) 29 | 30 | // if err != nil { 31 | // t.Fatalf("Failed to create Infisical client: %v", err) 32 | // } 33 | 34 | // secrets, err := client.Secrets().List(infisical.ListSecretsOptions{ 35 | // ProjectID: "PROJECT_ID", 36 | // Environment: "ENV_SLUG", 37 | // }) 38 | 39 | // if err != nil { 40 | // t.Fatalf("Failed to list secrets: %v", err) 41 | // } 42 | 43 | // if len(secrets) == 0 { 44 | // t.Fatalf("No secrets found") 45 | // } 46 | 47 | // t.Logf("Secrets: %v", secrets) 48 | 49 | // } 50 | -------------------------------------------------------------------------------- /test/secrets_batch_create_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | infisical "github.com/infisical/go-sdk" 8 | ) 9 | 10 | func TestBatchCreateSecrets(t *testing.T) { 11 | client := infisical.NewInfisicalClient(context.Background(), infisical.Config{ 12 | SiteUrl: "http://localhost:8080", 13 | AutoTokenRefresh: true, 14 | }) 15 | 16 | client.Auth().SetAccessToken("") 17 | 18 | secs, err := client.Secrets().Batch().Create(infisical.BatchCreateSecretsOptions{ 19 | Environment: "dev", 20 | SecretPath: "/", 21 | ProjectID: "06c4d805-ac8a-456f-906f-1319554d15ec", 22 | Secrets: []infisical.BatchCreateSecret{ 23 | { 24 | SecretKey: "test3", 25 | SecretValue: "test1", 26 | }, 27 | { 28 | SecretKey: "test4", 29 | SecretValue: "test2", 30 | }, 31 | }, 32 | }) 33 | 34 | if err != nil { 35 | t.Fatalf("Failed to create secrets: %v", err) 36 | } 37 | 38 | t.Logf("Secrets: %v", secs) 39 | } 40 | -------------------------------------------------------------------------------- /test/ssh_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | // import ( 4 | // "context" 5 | // "encoding/json" 6 | // "fmt" 7 | // "os" 8 | // "testing" 9 | 10 | // infisical "github.com/infisical/go-sdk" 11 | // ) 12 | 13 | // func TestSshIssueCreds(t *testing.T) { 14 | // client := infisical.NewInfisicalClient(context.Background(), infisical.Config{ 15 | // SiteUrl: "http://localhost:8080", 16 | // AutoTokenRefresh: true, 17 | // }) 18 | 19 | // // Authenticate using Universal Auth 20 | // _, err := client.Auth().UniversalAuthLogin("", "") 21 | // if err != nil { 22 | // fmt.Printf("Authentication failed: %v\n", err) 23 | // os.Exit(1) 24 | // } 25 | 26 | // // Test adding SSH host 27 | // _, err = client.Ssh().AddSshHost(infisical.AddSshHostOptions{ 28 | // ProjectID: "", 29 | // Hostname: "", 30 | // Alias: "", 31 | // }) 32 | // if err != nil { 33 | // fmt.Printf("Failed to add SSH host: %v\n", err) 34 | // os.Exit(1) 35 | // } 36 | 37 | // // Test getting SSH hosts the user has access to 38 | // hosts, err := client.Ssh().GetSshHosts(infisical.GetSshHostsOptions{}) 39 | // if err != nil { 40 | // t.Fatalf("Failed to fetch SSH hosts: %v", err) 41 | // } 42 | 43 | // if len(hosts) == 0 { 44 | // t.Fatalf("No SSH hosts returned") 45 | // } 46 | 47 | // fmt.Println("Got SSH hosts:") 48 | // for _, host := range hosts { 49 | // fmt.Printf("- Host: %s (ID: %s)\n", host.Hostname, host.ID) 50 | // } 51 | 52 | // // Test getting user CA public key for first host 53 | // userCaKey, err := client.Ssh().GetSshHostUserCaPublicKey(hosts[0].ID) 54 | // if err != nil { 55 | // t.Fatalf("Failed to get user CA public key: %v", err) 56 | // } 57 | 58 | // hostCaKey, err := client.Ssh().GetSshHostHostCaPublicKey(hosts[0].ID) 59 | // if err != nil { 60 | // t.Fatalf("Failed to get host CA public key: %v", err) 61 | // } 62 | 63 | // fmt.Printf("User CA Public Key for host %s:\n%s\n", hosts[0].Hostname, userCaKey) 64 | 65 | // for _, host := range hosts { 66 | // hostJson, err := json.MarshalIndent(host, "", " ") 67 | // if err != nil { 68 | // t.Errorf("Failed to marshal host %s: %v", host.ID, err) 69 | // continue 70 | // } 71 | // fmt.Println(string(hostJson)) 72 | // } 73 | 74 | // // Pick the first host 75 | // targetHost := hosts[0] 76 | 77 | // // Test issuing SSH cert for user 78 | // creds, err := client.Ssh().IssueSshHostUserCert(targetHost.ID, infisical.IssueSshHostUserCertOptions{ 79 | // LoginUser: "ec2-user", // or whatever login user is appropriate 80 | // }) 81 | // if err != nil { 82 | // t.Fatalf("Failed to issue SSH credentials from host %s: %v", targetHost.ID, err) 83 | // } 84 | 85 | // // Display the credentials 86 | // credsJson, err := json.MarshalIndent(creds, "", " ") 87 | // if err != nil { 88 | // t.Fatalf("Failed to marshal issued credentials: %v", err) 89 | // } 90 | // fmt.Println("Issued user credentials:") 91 | // fmt.Println(string(credsJson)) 92 | 93 | // // Test issuing SSH cert for host 94 | // creds2, err := client.Ssh().IssueSshHostHostCert(targetHost.ID, infisical.IssueSshHostHostCertOptions{ 95 | // PublicKey: "", 96 | // }) 97 | // if err != nil { 98 | // t.Fatalf("Failed to issue SSH credentials from host %s: %v", targetHost.ID, err) 99 | // } 100 | 101 | // // Display the credentials 102 | // creds2Json, err := json.MarshalIndent(creds2, "", " ") 103 | // if err != nil { 104 | // t.Fatalf("Failed to marshal issued credentials: %v", err) 105 | // } 106 | // fmt.Println("Issued credentials:") 107 | // fmt.Println(string(creds2Json)) 108 | 109 | // // Test issuing SSH credentials 110 | // creds, err := client.Ssh().IssueCredentials(infisical.IssueSshCredsOptions{ 111 | // CertificateTemplateID: "", 112 | // Principals: []string{"ec2-user"}, 113 | // }) 114 | 115 | // if err != nil { 116 | // t.Fatalf("Failed to issue SSH credentials: %v", err) 117 | // } 118 | 119 | // // Test signing SSH public key 120 | // creds2, err := client.Ssh().SignKey(infisical.SignSshPublicKeyOptions{ 121 | // CertificateTemplateID: "", 122 | // Principals: []string{"ec2-user"}, 123 | // PublicKey: "ssh-rsa ...", 124 | // }) 125 | 126 | // if err != nil { 127 | // t.Fatalf("Failed to sign SSH public key: %v", err) 128 | // } 129 | 130 | // fmt.Print("Newly-issued SSH credentials: ", creds) 131 | // fmt.Print("Signed SSH credential: ", creds2) 132 | // } 133 | -------------------------------------------------------------------------------- /test/universal_auth_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | // import ( 4 | // "os" 5 | // "testing" 6 | 7 | // infisical "github.com/infisical/go-sdk" 8 | // ) 9 | 10 | // func TestUniversalAuthLogin(t *testing.T) { 11 | 12 | // client, err := infisical.NewInfisicalClient(infisical.Config{ 13 | // Auth: infisical.Authentication{ 14 | // UniversalAuth: infisical.UniversalAuth{ 15 | // ClientID: os.Getenv("GO_SDK_TEST_UNIVERSAL_AUTH_CLIENT_ID"), 16 | // ClientSecret: os.Getenv("GO_SDK_TEST_UNIVERSAL_AUTH_CLIENT_SECRET"), 17 | // }, 18 | // }, 19 | // }) 20 | 21 | // if err != nil { 22 | // t.Fatalf("Failed to create Infisical client: %v", err) 23 | // } 24 | 25 | // secrets, err := client.Secrets().List(infisical.ListSecretsOptions{ 26 | // ProjectID: os.Getenv("GO_SDK_TEST_PROJECT_ID"), 27 | // Environment: "dev", 28 | // }) 29 | 30 | // if err != nil { 31 | // t.Fatalf("Failed to list secrets: %v", err) 32 | // } 33 | 34 | // if len(secrets) == 0 { 35 | // t.Fatalf("No secrets found") 36 | // } 37 | 38 | // t.Logf("Secrets: %v", secrets) 39 | 40 | // } 41 | --------------------------------------------------------------------------------