Skip to content

Commit

Permalink
Merge pull request #964 from lindseysimple/issue-963
Browse files Browse the repository at this point in the history
feat: Add model/DTOs and HTTP client for security-proxy-auth
  • Loading branch information
cloudxxx8 authored Jan 6, 2025
2 parents 3954224 + 8d9ce4b commit a17a865
Show file tree
Hide file tree
Showing 12 changed files with 495 additions and 0 deletions.
50 changes: 50 additions & 0 deletions clients/http/auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//
// Copyright (C) 2024 IOTech Ltd
//
// SPDX-License-Identifier: Apache-2.0

package http

import (
"context"

"github.com/edgexfoundry/go-mod-core-contracts/v4/clients/http/utils"
"github.com/edgexfoundry/go-mod-core-contracts/v4/clients/interfaces"
"github.com/edgexfoundry/go-mod-core-contracts/v4/common"
dtoCommon "github.com/edgexfoundry/go-mod-core-contracts/v4/dtos/common"
"github.com/edgexfoundry/go-mod-core-contracts/v4/dtos/requests"
"github.com/edgexfoundry/go-mod-core-contracts/v4/dtos/responses"
"github.com/edgexfoundry/go-mod-core-contracts/v4/errors"
)

type AuthClient struct {
baseUrl string
authInjector interfaces.AuthenticationInjector
}

// NewAuthClient creates an instance of AuthClient
func NewAuthClient(baseUrl string, authInjector interfaces.AuthenticationInjector) interfaces.AuthClient {
return &AuthClient{
baseUrl: baseUrl,
authInjector: authInjector,
}
}

// AddKey adds new key
func (ac *AuthClient) AddKey(ctx context.Context, req requests.AddKeyDataRequest) (dtoCommon.BaseResponse, errors.EdgeX) {
var response dtoCommon.BaseResponse
err := utils.PostRequestWithRawData(ctx, &response, ac.baseUrl, common.ApiKeyRoute, nil, req, ac.authInjector)
if err != nil {
return response, errors.NewCommonEdgeXWrapper(err)
}
return response, nil
}

func (ac *AuthClient) VerificationKeyByIssuer(ctx context.Context, issuer string) (res responses.KeyDataResponse, err errors.EdgeX) {
path := common.NewPathBuilder().SetPath(common.ApiKeyRoute).SetPath(common.VerificationKeyType).SetPath(common.Issuer).SetNameFieldPath(issuer).BuildPath()
err = utils.GetRequest(ctx, &res, ac.baseUrl, path, nil, ac.authInjector)
if err != nil {
return res, errors.NewCommonEdgeXWrapper(err)
}
return res, nil
}
43 changes: 43 additions & 0 deletions clients/http/auth_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//
// Copyright (C) 2024 IOTech Ltd
//
// SPDX-License-Identifier: Apache-2.0

package http

import (
"context"
"net/http"
"testing"

"github.com/edgexfoundry/go-mod-core-contracts/v4/common"
dtoCommon "github.com/edgexfoundry/go-mod-core-contracts/v4/dtos/common"
"github.com/edgexfoundry/go-mod-core-contracts/v4/dtos/requests"
"github.com/edgexfoundry/go-mod-core-contracts/v4/dtos/responses"

"github.com/stretchr/testify/require"
)

func TestAddKey(t *testing.T) {
ts := newTestServer(http.MethodPost, common.ApiKeyRoute, dtoCommon.BaseResponse{})
defer ts.Close()

client := NewAuthClient(ts.URL, NewNullAuthenticationInjector())
res, err := client.AddKey(context.Background(), requests.AddKeyDataRequest{})
require.NoError(t, err)
require.IsType(t, dtoCommon.BaseResponse{}, res)
}

func TestVerificationKeyByIssuer(t *testing.T) {
mockIssuer := "mockIssuer"

path := common.NewPathBuilder().EnableNameFieldEscape(false).
SetPath(common.ApiKeyRoute).SetPath(common.VerificationKeyType).SetPath(common.Issuer).SetNameFieldPath(mockIssuer).BuildPath()
ts := newTestServer(http.MethodGet, path, responses.KeyDataResponse{})
defer ts.Close()

client := NewAuthClient(ts.URL, NewNullAuthenticationInjector())
res, err := client.VerificationKeyByIssuer(context.Background(), mockIssuer)
require.NoError(t, err)
require.IsType(t, responses.KeyDataResponse{}, res)
}
23 changes: 23 additions & 0 deletions clients/interfaces/auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// Copyright (C) 2024 IOTech Ltd
//
// SPDX-License-Identifier: Apache-2.0

package interfaces

import (
"context"

"github.com/edgexfoundry/go-mod-core-contracts/v4/dtos/common"
"github.com/edgexfoundry/go-mod-core-contracts/v4/dtos/requests"
"github.com/edgexfoundry/go-mod-core-contracts/v4/dtos/responses"
"github.com/edgexfoundry/go-mod-core-contracts/v4/errors"
)

// AuthClient defines the interface for interactions with the auth API endpoint on the security-proxy-auth service.
type AuthClient interface {
// AddKey adds the JWT signing or verification key
AddKey(ctx context.Context, req requests.AddKeyDataRequest) (common.BaseResponse, errors.EdgeX)
// VerificationKeyByIssuer returns the JWT verification key by the specified issuer
VerificationKeyByIssuer(ctx context.Context, issuer string) (res responses.KeyDataResponse, err errors.EdgeX)
}
96 changes: 96 additions & 0 deletions clients/interfaces/mocks/AuthClient.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions common/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ const (
ApiAllRegistrationsRoute = ApiRegisterRoute + "/" + All
ApiKVSByKeyRoute = ApiKVSRoute + "/" + Key + "/:" + Key
ApiRegistrationByServiceIdRoute = ApiRegisterRoute + "/" + ServiceId + "/:" + ServiceId

ApiKeyRoute = ApiBase + "/key"
ApiVerificationKeyByIssuerRoute = ApiKeyRoute + "/" + VerificationKeyType + "/" + Issuer + "/:" + Issuer
)

// Constants related to defined url path names and parameters in the v3 service APIs
Expand Down Expand Up @@ -394,3 +397,10 @@ const (
// App Service Topics
// App Service topics remain configurable inorder to filter by subscription.
)

// Constants related to the security-proxy-auth service
const (
VerificationKeyType = "verification"
SigningKeyType = "signing"
Issuer = "issuer"
)
27 changes: 27 additions & 0 deletions dtos/keydata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// Copyright (C) 2024 IOTech Ltd
//
// SPDX-License-Identifier: Apache-2.0

package dtos

import (
"strings"

"github.com/edgexfoundry/go-mod-core-contracts/v4/models"
)

type KeyData struct {
Issuer string `json:"issuer" validate:"required"`
Type string `json:"type" validate:"omitempty,oneof=verification signing"`
Key string `json:"key" validate:"required"`
}

// ToKeyDataModel transforms the KeyData DTO to the KeyData Model
func ToKeyDataModel(keyData KeyData) models.KeyData {
return models.KeyData{
Issuer: keyData.Issuer,
Type: strings.ToLower(keyData.Type),
Key: keyData.Key,
}
}
33 changes: 33 additions & 0 deletions dtos/keydata_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//
// Copyright (C) 2024 IOTech Ltd
//
// SPDX-License-Identifier: Apache-2.0

package dtos

import (
"testing"

"github.com/edgexfoundry/go-mod-core-contracts/v4/models"

"github.com/stretchr/testify/require"
)

func TestToKeyDataModel(t *testing.T) {
mockIssuer := "mockIssuer"
mockType := "verification"
mockKey := "mockKey"
mockKeyDataDTO := KeyData{
Issuer: mockIssuer,
Type: mockType,
Key: mockKey,
}
mockModel := models.KeyData{
Issuer: mockIssuer,
Type: mockType,
Key: mockKey,
}

model := ToKeyDataModel(mockKeyDataDTO)
require.Equal(t, mockModel, model)
}
44 changes: 44 additions & 0 deletions dtos/requests/keydata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// Copyright (C) 2024 IOTech Ltd
//
// SPDX-License-Identifier: Apache-2.0

package requests

import (
"encoding/json"

"github.com/edgexfoundry/go-mod-core-contracts/v4/common"
"github.com/edgexfoundry/go-mod-core-contracts/v4/dtos"
dtoCommon "github.com/edgexfoundry/go-mod-core-contracts/v4/dtos/common"
"github.com/edgexfoundry/go-mod-core-contracts/v4/errors"
)

// AddKeyDataRequest defines the Request Content for POST Key DTO.
type AddKeyDataRequest struct {
dtoCommon.BaseRequest `json:",inline"`
KeyData dtos.KeyData `json:"keyData"`
}

// Validate satisfies the Validator interface
func (a *AddKeyDataRequest) Validate() error {
err := common.Validate(a)
return err
}

// UnmarshalJSON implements the Unmarshaler interface for the AddUserRequest type
func (a *AddKeyDataRequest) UnmarshalJSON(b []byte) error {
var alias struct {
dtoCommon.BaseRequest
KeyData dtos.KeyData
}
if err := json.Unmarshal(b, &alias); err != nil {
return errors.NewCommonEdgeX(errors.KindContractInvalid, "Failed to unmarshal request body as JSON.", err)
}

*a = AddKeyDataRequest(alias)
if err := a.Validate(); err != nil {
return err
}
return nil
}
Loading

0 comments on commit a17a865

Please sign in to comment.