Refactor OIDC-based auth mechanism (#2049)

This PR changes the two flavors of OIDC authentication mechanisms to
verify the same audience. This allows the same token to pass both
mechanisms. Previously the regular OIDC flavor uses the project id as
its required audience, which does not work for local user credentials
(such as ones used by the nomulus tool), which requires a valid OAuth
client ID as audience when minting the token (project id is NOT a valid
OAuth client ID).

I considered allowing multiple audiences, but the result is not as clean
as just using the same everywhere, because the fall-through logic would
have generated a lot of noises for failed attempts.

This PR also changes the client side to solely use OIDC token whenever
possible, including the proxy, cloud scheduler and cloud tasks. The nomulus
tool still uses OAuth access token by default because it requires USER level
authentication, which in turn requires us to fill the User table with objects
corresponding to the email address of everyone needing access to the tool.

TESTED=verified each client is able to make authenticated calls on QA with or
without IAP.
This commit is contained in:
Lai Jiang 2023-06-27 13:10:31 -04:00 committed by GitHub
parent cf1a148208
commit fdfbb9572d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
56 changed files with 565 additions and 891 deletions

View file

@ -26,10 +26,14 @@ import (
"os"
"os/exec"
"strings"
"gopkg.in/yaml.v3"
)
var projectName string
var clientId string
const GcpLocation = "us-central1"
type SyncManager[T Task | Queue] interface {
@ -74,6 +78,12 @@ type TasksSyncManager struct {
ServiceAccountEmail string
}
type YamlEntries struct {
Auth struct {
OauthClientId string `yaml:"oauthClientId"`
} `yaml:"auth"`
}
type XmlEntries struct {
XMLName xml.Name `xml:"entries"`
Tasks []Task `xml:"task"`
@ -180,7 +190,7 @@ func (manager TasksSyncManager) getArgs(task Task, operationType string) []strin
"--description", description,
"--http-method", "get",
"--oidc-service-account-email", getCloudSchedulerServiceAccountEmail(),
"--oidc-token-audience", projectName,
"--oidc-token-audience", clientId,
}
}
@ -301,21 +311,37 @@ func getExistingEntries(cmd *exec.Cmd) ExistingEntries {
}
func main() {
if len(os.Args) < 3 || os.Args[1] == "" || os.Args[2] == "" {
panic("Error - Invalid Parameters.\nRequired params: 1 - config file path; 2 - project name;")
if len(os.Args) < 4 || os.Args[1] == "" || os.Args[2] == "" || os.Args[3] == "" {
panic("Error - Invalid Parameters.\n" +
"Required params: 1 - Nomulu config YAML path; 2 - config XML path; 3 - project name;")
}
// Config file path
configFileLocation := os.Args[1]
// Nomulus YAML config file path, used to extract OAuth client ID.
nomulusConfigFileLocation := os.Args[1]
// XML config file path
configFileLocation := os.Args[2]
// Project name where to submit the tasks
projectName = os.Args[2]
projectName = os.Args[3]
log.Default().Println("Filepath " + configFileLocation)
log.Default().Println("YAML Filepath " + nomulusConfigFileLocation)
yamlFile, err := os.Open(nomulusConfigFileLocation)
if err != nil {
panic(err)
}
defer yamlFile.Close()
byteValue, _ := io.ReadAll(yamlFile)
var yamlEntries YamlEntries
if err := yaml.Unmarshal(byteValue, &yamlEntries); err != nil {
panic("Failed to parse YAML file entries: " + err.Error())
}
clientId = yamlEntries.Auth.OauthClientId
log.Default().Println("XML Filepath " + configFileLocation)
xmlFile, err := os.Open(configFileLocation)
if err != nil {
panic(err)
}
defer xmlFile.Close()
byteValue, _ := io.ReadAll(xmlFile)
byteValue, _ = io.ReadAll(xmlFile)
var xmlEntries XmlEntries
if err := xml.Unmarshal(byteValue, &xmlEntries); err != nil {
panic("Failed to parse xml file entries: " + err.Error())