github.com/Axway/agent-sdk@v1.1.101/pkg/apic/specoas2processor.go (about) 1 package apic 2 3 import ( 4 "encoding/json" 5 "net" 6 "sort" 7 "strconv" 8 "strings" 9 10 "github.com/Axway/agent-sdk/pkg/util" 11 coreerrors "github.com/Axway/agent-sdk/pkg/util/errors" 12 "github.com/getkin/kin-openapi/openapi2" 13 ) 14 15 var validOA2Schemes = map[string]bool{"http": true, "https": true, "ws": true, "wss": true} 16 17 const ( 18 oasSecurityAPIKey = "apiKey" 19 oasSecurityOauth = "oauth2" 20 oasSecurityBasic = "basic" 21 oasSecurityHttp = "http" 22 ) 23 24 // oas2SpecProcessor parses and validates an OAS2 spec, and exposes methods to modify the content of the spec. 25 type oas2SpecProcessor struct { 26 spec *openapi2.T 27 scopes map[string]string 28 authPolicies []string 29 apiKeyInfo []APIKeyInfo 30 } 31 32 func newOas2Processor(oas2Spec *openapi2.T) *oas2SpecProcessor { 33 return &oas2SpecProcessor{spec: oas2Spec} 34 } 35 36 func (p *oas2SpecProcessor) GetResourceType() string { 37 return Oas2 38 } 39 40 // GetVersion - 41 func (p *oas2SpecProcessor) GetVersion() string { 42 return p.spec.Info.Version 43 } 44 45 // GetEndpoints - 46 func (p *oas2SpecProcessor) GetEndpoints() ([]EndpointDefinition, error) { 47 endPoints := []EndpointDefinition{} 48 swaggerHostElements := strings.Split(p.spec.Host, ":") 49 host := swaggerHostElements[0] 50 port := 0 51 if len(swaggerHostElements) > 1 { 52 swaggerPort, err := strconv.Atoi(swaggerHostElements[1]) 53 if err == nil { 54 port = swaggerPort 55 } 56 } 57 58 if host == "" { 59 return nil, coreerrors.Wrap(ErrSetSpecEndPoints, "no host defined in the specification") 60 } 61 62 // If schemes are specified create endpoint for each scheme 63 if len(p.spec.Schemes) > 0 { 64 for _, protocol := range p.spec.Schemes { 65 if !validOA2Schemes[protocol] { 66 return nil, coreerrors.Wrap(ErrSetSpecEndPoints, "invalid endpoint scheme defined in specification") 67 } 68 endPoint := createEndpointDefinition(protocol, host, port, p.spec.BasePath) 69 endPoints = append(endPoints, endPoint) 70 } 71 } 72 73 // If no schemes are specified create endpoint with default scheme 74 if len(endPoints) == 0 { 75 endPoint := createEndpointDefinition("https", host, port, p.spec.BasePath) 76 endPoints = append(endPoints, endPoint) 77 } 78 return endPoints, nil 79 } 80 81 func (p *oas2SpecProcessor) ParseAuthInfo() { 82 authPolicies := []string{} 83 keyInfo := []APIKeyInfo{} 84 scopes := make(map[string]string) 85 for _, scheme := range p.spec.SecurityDefinitions { 86 switch scheme.Type { 87 case oasSecurityBasic: 88 authPolicies = append(authPolicies, Basic) 89 case oasSecurityAPIKey: 90 authPolicies = append(authPolicies, Apikey) 91 keyInfo = append(keyInfo, APIKeyInfo{ 92 Location: scheme.In, 93 Name: scheme.Name, 94 }) 95 case oasSecurityOauth: 96 authPolicies = append(authPolicies, Oauth) 97 for scope, val := range scheme.Scopes { 98 scopes[strings.TrimSpace(scope)] = strings.TrimSpace(val) 99 } 100 } 101 } 102 p.authPolicies = util.RemoveDuplicateValuesFromStringSlice(authPolicies) 103 sort.Strings(p.authPolicies) 104 p.apiKeyInfo = keyInfo 105 p.scopes = scopes 106 } 107 108 func (p *oas2SpecProcessor) GetAuthPolicies() []string { 109 return p.authPolicies 110 } 111 112 func (p *oas2SpecProcessor) GetOAuthScopes() map[string]string { 113 return p.scopes 114 } 115 116 func (p *oas2SpecProcessor) GetAPIKeyInfo() []APIKeyInfo { 117 return p.apiKeyInfo 118 } 119 120 func (p *oas2SpecProcessor) GetTitle() string { 121 return p.spec.Info.Title 122 } 123 124 func (p *oas2SpecProcessor) GetDescription() string { 125 return p.spec.Info.Description 126 } 127 128 func (p *oas2SpecProcessor) StripSpecAuth() { 129 p.spec.SecurityDefinitions = map[string]*openapi2.SecurityScheme{} 130 p.spec.Security = make(openapi2.SecurityRequirements, 0) 131 } 132 133 func (p *oas2SpecProcessor) GetSecurityBuilder() SecurityBuilder { 134 return newSpecSecurityBuilder(oas2) 135 } 136 func (p *oas2SpecProcessor) AddSecuritySchemes(authSchemes map[string]interface{}) { 137 // order authSchemas by name 138 for _, name := range util.OrderedKeys(authSchemes) { 139 scheme := authSchemes[name] 140 p.spec.SecurityDefinitions[name], _ = scheme.(*openapi2.SecurityScheme) 141 142 // get scopes in array 143 scopes := []string{} 144 for s := range p.spec.SecurityDefinitions[name].Scopes { 145 scopes = append(scopes, s) 146 } 147 148 // order the scopes 149 sort.Strings(scopes) 150 151 // add security to spec 152 p.spec.Security = append(p.spec.Security, map[string][]string{ 153 name: scopes, 154 }) 155 } 156 } 157 158 func (p *oas2SpecProcessor) GetSpecBytes() []byte { 159 s, _ := json.Marshal(p.spec) 160 return s 161 } 162 163 func createEndpointDefinition(scheme, host string, port int, basePath string) EndpointDefinition { 164 path := "/" 165 if basePath != "" { 166 path = basePath 167 } 168 // If a port is not given, use lookup the default 169 if port == 0 { 170 port, _ = net.LookupPort("tcp", scheme) 171 } 172 return EndpointDefinition{ 173 Host: host, 174 Port: int32(port), 175 Protocol: scheme, 176 BasePath: path, 177 } 178 }