-
Notifications
You must be signed in to change notification settings - Fork 4
/
idp.go
116 lines (95 loc) · 2.9 KB
/
idp.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package idp
import (
"bytes"
"context"
"crypto/rsa"
"crypto/x509"
"encoding/json"
"encoding/pem"
"errors"
"fmt"
"github.com/Interhyp/metadata-service/acorns/repository"
aurestclientprometheus "github.com/StephanHCB/go-autumn-restclient-prometheus"
aurestclientapi "github.com/StephanHCB/go-autumn-restclient/api"
auresthttpclient "github.com/StephanHCB/go-autumn-restclient/implementation/httpclient"
aurestlogging "github.com/StephanHCB/go-autumn-restclient/implementation/requestlogging"
librepo "github.com/StephanHCB/go-backend-service-common/acorns/repository"
"github.com/lestrrat-go/jwx/v2/jwk"
"net/http"
"time"
)
import _ "github.com/go-git/go-git/v5"
type Impl struct {
Configuration librepo.Configuration
CustomConfiguration repository.CustomConfiguration
Logging librepo.Logging
IDPClient aurestclientapi.Client
PEMKeySet []string
}
func (r *Impl) Setup(ctx context.Context) error {
r.Logging.Logger().Ctx(ctx).Info().Print("setting up idp connector")
client, err := auresthttpclient.New(10*time.Second, nil, nil)
if err != nil {
return err
}
aurestclientprometheus.InstrumentHttpClient(client)
logWrapper := aurestlogging.New(client)
r.IDPClient = logWrapper
r.PEMKeySet = make([]string, 0)
return nil
}
func (r *Impl) ObtainKeySet(ctx context.Context) error {
keysetUrl := r.CustomConfiguration.KeySetUrl()
responseMap := make(map[string]interface{})
response := &aurestclientapi.ParsedResponse{
Body: &responseMap,
}
err := r.IDPClient.Perform(ctx, http.MethodGet, keysetUrl, nil, response)
if err != nil {
return err
}
if response.Status != http.StatusOK {
return errors.New("did not receive http 200 from idp")
}
// we have ensured a structured response, so it can't try to misinterpret e.g. blank pages, httpd error messages, ...
keySetBytes, err := json.Marshal(&responseMap)
if err != nil {
return err
}
keySet, err := jwk.Parse(keySetBytes)
if err != nil {
return fmt.Errorf("failed to parse keyset: %v", err)
}
for i := 0; i < keySet.Len(); i++ {
key, ok := keySet.Key(i)
if !ok {
return fmt.Errorf("failed to get key #%d from keyset", i+1)
}
pubKey := &rsa.PublicKey{}
err = key.Raw(pubKey)
if err != nil {
return fmt.Errorf("failed to extract raw rsa public key for key #%d: %s", i+1, err.Error())
}
pubData, err := x509.MarshalPKIXPublicKey(pubKey)
if err != nil {
return fmt.Errorf("failed to marshal key #%d to public key: %s", i+1, err.Error())
}
output := bytes.Buffer{}
err = pem.Encode(&output, &pem.Block{
Type: "PUBLIC KEY",
Bytes: pubData,
})
if err != nil {
return fmt.Errorf("failed to pem encode key #%d: %s", i+1, err.Error())
}
r.PEMKeySet = append(r.PEMKeySet, output.String())
}
return nil
}
func (r *Impl) GetKeySet(ctx context.Context) []string {
return r.PEMKeySet
}
func (r *Impl) VerifyToken(ctx context.Context, token string) error {
// TODO implement
return nil
}