Skip to content

Commit 318b41b

Browse files
authored
Merge pull request #24 from Infisical/ssh-cert
Add SSH issue and sign operations to SDK
2 parents fc1d696 + d68500d commit 318b41b

File tree

7 files changed

+208
-0
lines changed

7 files changed

+208
-0
lines changed

client.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ type InfisicalClient struct {
3434
auth AuthInterface
3535
dynamicSecrets DynamicSecretsInterface
3636
kms KmsInterface
37+
ssh SshInterface
3738
}
3839

3940
type InfisicalClientInterface interface {
@@ -43,6 +44,7 @@ type InfisicalClientInterface interface {
4344
Auth() AuthInterface
4445
DynamicSecrets() DynamicSecretsInterface
4546
Kms() KmsInterface
47+
Ssh() SshInterface
4648
}
4749

4850
type Config struct {
@@ -120,6 +122,7 @@ func NewInfisicalClient(context context.Context, config Config) InfisicalClientI
120122
client.auth = NewAuth(client)
121123
client.dynamicSecrets = NewDynamicSecrets(client)
122124
client.kms = NewKms(client)
125+
client.ssh = NewSsh(client)
123126

124127
if config.AutoTokenRefresh {
125128
go client.handleTokenLifeCycle(context)
@@ -185,6 +188,10 @@ func (c *InfisicalClient) Kms() KmsInterface {
185188
return c.kms
186189
}
187190

191+
func (c *InfisicalClient) Ssh() SshInterface {
192+
return c.ssh
193+
}
194+
188195
func (c *InfisicalClient) handleTokenLifeCycle(context context.Context) {
189196
var warningPrinted = false
190197
authStrategies := map[util.AuthMethod]func(cred interface{}) (credential MachineIdentityCredential, err error){

packages/api/ssh/issue_ssh_creds.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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/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+
}

packages/api/ssh/models.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package api
2+
3+
import (
4+
"github.com/infisical/go-sdk/packages/util"
5+
)
6+
7+
type SignSshPublicKeyV1Request struct {
8+
ProjectID string `json:"projectId"`
9+
TemplateName string `json:"templateName"`
10+
PublicKey string `json:"publicKey"`
11+
KeyAlgorithm util.CertKeyAlgorithm `json:"keyAlgorithm,omitempty"`
12+
CertType util.SshCertType `json:"certType,omitempty"`
13+
Principals []string `json:"principals"`
14+
TTL string `json:"ttl,omitempty"`
15+
KeyID string `json:"keyId,omitempty"`
16+
}
17+
18+
type SignSshPublicKeyV1Response struct {
19+
SerialNumber string `json:"serialNumber"`
20+
SignedKey string `json:"signedKey"`
21+
}
22+
23+
type IssueSshCredsV1Request struct {
24+
ProjectID string `json:"projectId"`
25+
TemplateName string `json:"templateName"`
26+
KeyAlgorithm util.CertKeyAlgorithm `json:"keyAlgorithm,omitempty"`
27+
CertType util.SshCertType `json:"certType,omitempty"`
28+
Principals []string `json:"principals"`
29+
TTL string `json:"ttl,omitempty"`
30+
KeyID string `json:"keyId,omitempty"`
31+
}
32+
33+
type IssueSshCredsV1Response struct {
34+
SerialNumber string `json:"serialNumber"`
35+
SignedKey string `json:"signedKey"`
36+
PrivateKey string `json:"privateKey"`
37+
PublicKey string `json:"publicKey"`
38+
KeyAlgorithm util.CertKeyAlgorithm `json:"keyAlgorithm"`
39+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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/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+
}

packages/util/constants.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,23 @@ const (
5454
OIDC_AUTH AuthMethod = "OIDC_AUTH"
5555
)
5656

57+
// SSH related:
58+
type CertKeyAlgorithm string
59+
60+
const (
61+
RSA2048 CertKeyAlgorithm = "RSA_2048"
62+
RSA4096 CertKeyAlgorithm = "RSA_4096"
63+
ECDSAP256 CertKeyAlgorithm = "EC_prime256v1"
64+
ECDSAP384 CertKeyAlgorithm = "EC_secp384r1"
65+
)
66+
67+
type SshCertType string
68+
69+
const (
70+
UserCert SshCertType = "user"
71+
HostCert SshCertType = "host"
72+
)
73+
5774
// General:
5875
const (
5976
DEFAULT_INFISICAL_API_URL = "https://app.infisical.com/api"

ssh.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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+
10+
type SshInterface interface {
11+
SignKey(options SignSshPublicKeyOptions) (api.SignSshPublicKeyV1Response, error)
12+
IssueCredentials(options IssueSshCredsOptions) (api.IssueSshCredsV1Response, error)
13+
}
14+
15+
type Ssh struct {
16+
client *InfisicalClient
17+
}
18+
19+
func (f *Ssh) SignKey(options SignSshPublicKeyOptions) (api.SignSshPublicKeyV1Response, error) {
20+
res, err := api.CallSignSshPublicKeyV1(f.client.httpClient, options)
21+
22+
if err != nil {
23+
return api.SignSshPublicKeyV1Response{}, err
24+
}
25+
26+
return res, nil
27+
}
28+
29+
func (f *Ssh) IssueCredentials(options IssueSshCredsOptions) (api.IssueSshCredsV1Response, error) {
30+
res, err := api.CallIssueSshCredsV1(f.client.httpClient, options)
31+
32+
if err != nil {
33+
return api.IssueSshCredsV1Response{}, err
34+
}
35+
36+
return res, nil
37+
}
38+
39+
func NewSsh(client *InfisicalClient) SshInterface {
40+
return &Ssh{client: client}
41+
}

test/ssh_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package test
2+
3+
// import (
4+
// "context"
5+
// "fmt"
6+
// "os"
7+
// "testing"
8+
9+
// infisical "github.com/infisical/go-sdk"
10+
// )
11+
12+
// func TestSshIssueCreds(t *testing.T) {
13+
// client := infisical.NewInfisicalClient(context.Background(), infisical.Config{
14+
// SiteUrl: "http://localhost:8080",
15+
// AutoTokenRefresh: true,
16+
// })
17+
18+
// // Authenticate using Universal Auth
19+
// _, err := client.Auth().UniversalAuthLogin(os.Getenv("GO_SDK_TEST_UNIVERSAL_AUTH_CLIENT_ID"), os.Getenv("GO_SDK_TEST_UNIVERSAL_AUTH_CLIENT_SECRET"))
20+
// if err != nil {
21+
// fmt.Printf("Authentication failed: %v\n", err)
22+
// os.Exit(1)
23+
// }
24+
25+
// // Test issuing SSH credentials
26+
// creds, err := client.Ssh().IssueCredentials(infisical.IssueSshCredsOptions{
27+
// ProjectID: os.Getenv("GO_SDK_TEST_PROJECT_ID"),
28+
// TemplateName: "template-name",
29+
// Principals: []string{"ec2-user"},
30+
// })
31+
32+
// if err != nil {
33+
// t.Fatalf("Failed to issue SSH credentials: %v", err)
34+
// }
35+
36+
// // Test signing SSH public key
37+
// creds2, err := client.Ssh().SignKey(infisical.SignSshPublicKeyOptions{
38+
// ProjectID: os.Getenv("GO_SDK_TEST_PROJECT_ID"),
39+
// TemplateName: "template-name",
40+
// Principals: []string{"ec2-user"},
41+
// PublicKey: "ssh-rsa ...",
42+
// })
43+
44+
// if err != nil {
45+
// t.Fatalf("Failed to sign SSH public key: %v", err)
46+
// }
47+
48+
// fmt.Print("Newly-issued SSH credentials: ", creds)
49+
// fmt.Print("Signed SSH credential: ", creds2)
50+
// }

0 commit comments

Comments
 (0)