This is an automated email from the ASF dual-hosted git repository.
tison pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar-client-go.git
The following commit(s) were added to refs/heads/master by this push:
new 4ebb3c7 Add data url format to read the key file (#883)
4ebb3c7 is described below
commit 4ebb3c7212e44b27e0096357eff510c51e556d40
Author: Zixuan Liu <[email protected]>
AuthorDate: Wed Nov 16 15:51:59 2022 +0800
Add data url format to read the key file (#883)
Signed-off-by: Zixuan Liu <[email protected]>
---
oauth2/client_credentials_provider.go | 6 +++
oauth2/client_credentials_provider_test.go | 78 ++++++++++++++++++++++++++++++
oauth2/data_url.go | 70 +++++++++++++++++++++++++++
oauth2/data_url_test.go | 58 ++++++++++++++++++++++
4 files changed, 212 insertions(+)
diff --git a/oauth2/client_credentials_provider.go
b/oauth2/client_credentials_provider.go
index c112225..5230ca3 100644
--- a/oauth2/client_credentials_provider.go
+++ b/oauth2/client_credentials_provider.go
@@ -57,6 +57,12 @@ func (k *KeyFileProvider) GetClientCredentials() (*KeyFile,
error) {
keyFile, err = ioutil.ReadFile(filename)
case strings.HasPrefix(k.KeyFile, DATA):
keyFile = []byte(strings.TrimPrefix(k.KeyFile, DATA))
+ case strings.HasPrefix(k.KeyFile, "data:"):
+ url, err := newDataURL(k.KeyFile)
+ if err != nil {
+ return nil, err
+ }
+ keyFile = url.Data
default:
keyFile, err = ioutil.ReadFile(k.KeyFile)
}
diff --git a/oauth2/client_credentials_provider_test.go
b/oauth2/client_credentials_provider_test.go
new file mode 100644
index 0000000..f47967b
--- /dev/null
+++ b/oauth2/client_credentials_provider_test.go
@@ -0,0 +1,78 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package oauth2
+
+import (
+ "encoding/base64"
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestNewClientCredentialsProviderFromKeyFile(t *testing.T) {
+ oauthType := "TYPE"
+ clientID := "CLIENT_ID"
+ ClientSecret := "CLIENT_SECRET"
+ ClientEmail := "CLIENT_EMAIL"
+ IssuerURL := "ISSUER_URL"
+ keyFile := &KeyFile{
+ Type: oauthType,
+ ClientID: clientID,
+ ClientSecret: ClientSecret,
+ ClientEmail: ClientEmail,
+ IssuerURL: IssuerURL,
+ }
+
+ b, err := json.Marshal(keyFile)
+ require.NoError(t, err)
+ tmpFile, err := ioutil.TempFile("", "key-file")
+ require.NoError(t, err)
+ defer func(name string) {
+ _ = os.Remove(name)
+ }(tmpFile.Name())
+ _, err = tmpFile.Write(b)
+ require.NoError(t, err)
+
+ jsonData := string(b)
+ base64Data := base64.StdEncoding.EncodeToString(b)
+
+ assertCredentials(t, fmt.Sprintf("file://%s", tmpFile.Name()), keyFile)
+ assertCredentials(t, fmt.Sprintf("data://%s", jsonData), keyFile)
+ assertCredentials(t, fmt.Sprintf("data:,%s", jsonData), keyFile)
+ assertCredentials(t, fmt.Sprintf("data:application/json,%s", jsonData),
keyFile)
+ assertCredentials(t, fmt.Sprintf("data:;base64,%s", base64Data),
keyFile)
+ assertCredentials(t, fmt.Sprintf("data:application/json;base64,%s",
base64Data), keyFile)
+}
+
+func TestNewInvalidClientCredentialsProviderFromKeyFile(t *testing.T) {
+ p := NewClientCredentialsProviderFromKeyFile("data:application/data,hi")
+ _, err := p.GetClientCredentials()
+ require.Error(t, err)
+}
+
+func assertCredentials(t *testing.T, keyfile string, expected *KeyFile) {
+ p := NewClientCredentialsProviderFromKeyFile(keyfile)
+ clientCredentials, err := p.GetClientCredentials()
+ require.NoError(t, err)
+ assert.Equal(t, expected, clientCredentials)
+}
diff --git a/oauth2/data_url.go b/oauth2/data_url.go
new file mode 100644
index 0000000..8d711f8
--- /dev/null
+++ b/oauth2/data_url.go
@@ -0,0 +1,70 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package oauth2
+
+import (
+ "encoding/base64"
+ "errors"
+ "regexp"
+)
+
+var errDataURLInvalid = errors.New("invalid data URL")
+
+// https://datatracker.ietf.org/doc/html/rfc2397
+var dataURLRegex =
regexp.MustCompile("^data:(?P<mimetype>[^;,]+)?(;(?P<charset>charset=[^;,]+))?"
+
+ "(;(?P<base64>base64))?,(?P<data>.+)")
+
+type dataURL struct {
+ url string
+ Mimetype string
+ Data []byte
+}
+
+func newDataURL(url string) (*dataURL, error) {
+ if !dataURLRegex.Match([]byte(url)) {
+ return nil, errDataURLInvalid
+ }
+
+ match := dataURLRegex.FindStringSubmatch(url)
+ if len(match) != 7 {
+ return nil, errDataURLInvalid
+ }
+
+ dataURL := &dataURL{
+ url: url,
+ }
+
+ mimetype := match[dataURLRegex.SubexpIndex("mimetype")]
+ if mimetype == "" {
+ mimetype = "text/plain"
+ }
+ dataURL.Mimetype = mimetype
+
+ data := match[dataURLRegex.SubexpIndex("data")]
+ if match[dataURLRegex.SubexpIndex("base64")] == "" {
+ dataURL.Data = []byte(data)
+ } else {
+ data, err := base64.StdEncoding.DecodeString(data)
+ if err != nil {
+ return nil, err
+ }
+ dataURL.Data = data
+ }
+
+ return dataURL, nil
+}
diff --git a/oauth2/data_url_test.go b/oauth2/data_url_test.go
new file mode 100644
index 0000000..8bdc880
--- /dev/null
+++ b/oauth2/data_url_test.go
@@ -0,0 +1,58 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package oauth2
+
+import (
+ "encoding/base64"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestNewDataURL(t *testing.T) {
+ rawURL := "data:,test"
+ url, err := newDataURL(rawURL)
+ require.NoError(t, err)
+ assert.Equal(t, "text/plain", url.Mimetype)
+ assert.Equal(t, "test", string(url.Data))
+
+ rawURL = "data:;base64," +
base64.StdEncoding.EncodeToString([]byte("test"))
+ url, err = newDataURL(rawURL)
+ require.NoError(t, err)
+ assert.Equal(t, "text/plain", url.Mimetype)
+ assert.Equal(t, "test", string(url.Data))
+
+ rawURL = "data:application/json,test"
+ url, err = newDataURL(rawURL)
+ require.NoError(t, err)
+ assert.Equal(t, "application/json", url.Mimetype)
+ assert.Equal(t, "test", string(url.Data))
+
+ rawURL = "data:application/json;base64," +
base64.StdEncoding.EncodeToString([]byte("test"))
+ url, err = newDataURL(rawURL)
+ require.NoError(t, err)
+ assert.Equal(t, "application/json", url.Mimetype)
+ assert.Equal(t, "test", string(url.Data))
+
+ rawURL = "data://test"
+ url, err = newDataURL(rawURL)
+ require.Nil(t, url)
+ assert.Error(t, err)
+ assert.EqualError(t, errDataURLInvalid, err.Error())
+}