Skip to content

Commit

Permalink
[credentialhelper] Add parser for flag syntax
Browse files Browse the repository at this point in the history
Progress on #15856

Closes #15906.

PiperOrigin-RevId: 462095541
Change-Id: I4d31ad2ae185b63f0945119483ffafd3ba121d3d
  • Loading branch information
Yannic authored and copybara-github committed Jul 20, 2022
1 parent 35bcb96 commit aa94b1b
Show file tree
Hide file tree
Showing 8 changed files with 471 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,22 @@

package com.google.devtools.build.lib.authandtls;

import com.google.auto.value.AutoValue;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.devtools.common.options.Converter;
import com.google.devtools.common.options.Converters.CommaSeparatedOptionListConverter;
import com.google.devtools.common.options.Converters.DurationConverter;
import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionDocumentationCategory;
import com.google.devtools.common.options.OptionEffectTag;
import com.google.devtools.common.options.OptionMetadataTag;
import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.OptionsParsingException;
import java.time.Duration;
import java.util.List;
import java.util.Optional;
import javax.annotation.Nullable;

/**
* Common options for authentication and TLS.
Expand Down Expand Up @@ -131,4 +138,53 @@ public class AuthAndTLSOptions extends OptionsBase {
+ "granularity; it is an error to set a value less than one second. If keep-alive "
+ "pings are disabled, then this setting is ignored.")
public Duration grpcKeepaliveTimeout;

/** One of the values of the `--credential_helper` flag. */
@AutoValue
public abstract static class UnresolvedScopedCredentialHelper {
/** Returns the scope of the credential helper (if any). */
public abstract Optional<String> getScope();

/** Returns the (unparsed) path of the credential helper. */
public abstract String getPath();
}

/** A {@link Converter} for the `--credential_helper` flag. */
public static final class UnresolvedScopedCredentialHelperConverter
extends Converter.Contextless<UnresolvedScopedCredentialHelper> {
public static final UnresolvedScopedCredentialHelperConverter INSTANCE =
new UnresolvedScopedCredentialHelperConverter();

@Override
public String getTypeDescription() {
return "An (unresolved) path to a credential helper for a scope.";
}

@Override
public UnresolvedScopedCredentialHelper convert(String input) throws OptionsParsingException {
Preconditions.checkNotNull(input);

int pos = input.indexOf('=');
if (pos >= 0) {
String scope = input.substring(0, pos);
if (Strings.isNullOrEmpty(scope)) {
throw new OptionsParsingException("Scope of credential helper must not be empty");
}
String path = checkPath(input.substring(pos + 1));
return new AutoValue_AuthAndTLSOptions_UnresolvedScopedCredentialHelper(
Optional.of(scope), path);
}

// `input` does not specify a scope.
return new AutoValue_AuthAndTLSOptions_UnresolvedScopedCredentialHelper(
Optional.empty(), checkPath(input));
}

private String checkPath(@Nullable String input) throws OptionsParsingException {
if (Strings.isNullOrEmpty(input)) {
throw new OptionsParsingException("Path to credential helper must not be empty");
}
return input;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public final class CredentialHelper {
}

@VisibleForTesting
Path getPath() {
public Path getPath() {
return path;
}

Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/google/devtools/build/lib/remote/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ java_library(
"//src/main/java/com/google/devtools/build/lib/analysis:top_level_artifact_context",
"//src/main/java/com/google/devtools/build/lib/analysis/platform:platform_utils",
"//src/main/java/com/google/devtools/build/lib/authandtls",
"//src/main/java/com/google/devtools/build/lib/authandtls/credentialhelper",
"//src/main/java/com/google/devtools/build/lib/bazel/repository/downloader",
"//src/main/java/com/google/devtools/build/lib/buildeventstream",
"//src/main/java/com/google/devtools/build/lib/clock",
Expand Down Expand Up @@ -102,6 +103,7 @@ java_library(
"//src/main/java/com/google/devtools/common/options",
"//src/main/protobuf:failure_details_java_proto",
"//third_party:auth",
"//third_party:auto_value",
"//third_party:caffeine",
"//third_party:flogger",
"//third_party:guava",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import build.bazel.remote.execution.v2.DigestFunction;
import build.bazel.remote.execution.v2.ServerCapabilities;
import com.google.auth.Credentials;
import com.google.auto.value.AutoValue;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Ascii;
import com.google.common.base.Preconditions;
Expand All @@ -45,11 +46,14 @@
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget;
import com.google.devtools.build.lib.analysis.test.TestProvider;
import com.google.devtools.build.lib.authandtls.AuthAndTLSOptions;
import com.google.devtools.build.lib.authandtls.AuthAndTLSOptions.UnresolvedScopedCredentialHelper;
import com.google.devtools.build.lib.authandtls.CallCredentialsProvider;
import com.google.devtools.build.lib.authandtls.GoogleAuthUtils;
import com.google.devtools.build.lib.authandtls.Netrc;
import com.google.devtools.build.lib.authandtls.NetrcCredentials;
import com.google.devtools.build.lib.authandtls.NetrcParser;
import com.google.devtools.build.lib.authandtls.credentialhelper.CredentialHelperEnvironment;
import com.google.devtools.build.lib.authandtls.credentialhelper.CredentialHelperProvider;
import com.google.devtools.build.lib.bazel.repository.downloader.Downloader;
import com.google.devtools.build.lib.buildeventstream.BuildEventArtifactUploader;
import com.google.devtools.build.lib.buildeventstream.LocalFilesArtifactUploader;
Expand Down Expand Up @@ -78,6 +82,7 @@
import com.google.devtools.build.lib.runtime.BuildEventArtifactUploaderFactory;
import com.google.devtools.build.lib.runtime.Command;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.runtime.CommandLinePathFactory;
import com.google.devtools.build.lib.runtime.RepositoryRemoteExecutor;
import com.google.devtools.build.lib.runtime.RepositoryRemoteExecutorFactory;
import com.google.devtools.build.lib.runtime.ServerBuilder;
Expand Down Expand Up @@ -1130,4 +1135,37 @@ static Credentials newCredentials(

return creds;
}

@VisibleForTesting
static CredentialHelperProvider newCredentialHelperProvider(
CredentialHelperEnvironment environment,
CommandLinePathFactory pathFactory,
List<UnresolvedScopedCredentialHelper> helpers)
throws IOException {
Preconditions.checkNotNull(environment);
Preconditions.checkNotNull(pathFactory);
Preconditions.checkNotNull(helpers);

CredentialHelperProvider.Builder builder = CredentialHelperProvider.builder();
for (UnresolvedScopedCredentialHelper helper : helpers) {
Optional<String> scope = helper.getScope();
Path path = pathFactory.create(environment.getClientEnvironment(), helper.getPath());
if (scope.isPresent()) {
builder.add(scope.get(), path);
} else {
builder.add(path);
}
}
return builder.build();
}

@VisibleForTesting
@AutoValue
abstract static class ScopedCredentialHelper {
/** Returns the scope of the credential helper (if any). */
public abstract Optional<String> getScope();

/** Returns the path of the credential helper. */
public abstract Path getPath();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ java_library(
),
deps = [
"//src/main/java/com/google/devtools/build/lib/authandtls",
"//src/main/java/com/google/devtools/common/options",
"//third_party:guava",
"//third_party:junit4",
"//third_party:truth",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// Copyright 2022 The Bazel Authors. All rights reserved.
//
// Licensed 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 com.google.devtools.build.lib.authandtls;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
import static org.junit.Assert.assertThrows;

import com.google.devtools.build.lib.authandtls.AuthAndTLSOptions.UnresolvedScopedCredentialHelper;
import com.google.devtools.build.lib.authandtls.AuthAndTLSOptions.UnresolvedScopedCredentialHelperConverter;
import com.google.devtools.common.options.OptionsParsingException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Test for {@link UnresolvedScopedCredentialHelperConverter}. */
@RunWith(JUnit4.class)
public class UnresolvedScopedCredentialHelperConverterTest {
@Test
public void convertAbsolutePath() throws Exception {
UnresolvedScopedCredentialHelper helper1 =
UnresolvedScopedCredentialHelperConverter.INSTANCE.convert("/absolute/path");
assertThat(helper1.getScope()).isEmpty();
assertThat(helper1.getPath()).isEqualTo("/absolute/path");

UnresolvedScopedCredentialHelper helper2 =
UnresolvedScopedCredentialHelperConverter.INSTANCE.convert("example.com=/absolute/path");
assertThat(helper2.getScope()).hasValue("example.com");
assertThat(helper2.getPath()).isEqualTo("/absolute/path");

UnresolvedScopedCredentialHelper helper3 =
UnresolvedScopedCredentialHelperConverter.INSTANCE.convert("*.example.com=/absolute/path");
assertThat(helper3.getScope()).hasValue("*.example.com");
assertThat(helper3.getPath()).isEqualTo("/absolute/path");
}

@Test
public void convertRootRelativePath() throws Exception {
UnresolvedScopedCredentialHelper helper1 =
UnresolvedScopedCredentialHelperConverter.INSTANCE.convert("%workspace%/path");
assertThat(helper1.getScope()).isEmpty();
assertThat(helper1.getPath()).isEqualTo("%workspace%/path");

UnresolvedScopedCredentialHelper helper2 =
UnresolvedScopedCredentialHelperConverter.INSTANCE.convert("example.com=%workspace%/path");
assertThat(helper2.getScope()).hasValue("example.com");
assertThat(helper2.getPath()).isEqualTo("%workspace%/path");

UnresolvedScopedCredentialHelper helper3 =
UnresolvedScopedCredentialHelperConverter.INSTANCE.convert(
"*.example.com=%workspace%/path");
assertThat(helper3.getScope()).hasValue("*.example.com");
assertThat(helper3.getPath()).isEqualTo("%workspace%/path");
}

@Test
public void convertPathLookup() throws Exception {
UnresolvedScopedCredentialHelper helper1 =
UnresolvedScopedCredentialHelperConverter.INSTANCE.convert("foo");
assertThat(helper1.getScope()).isEmpty();
assertThat(helper1.getPath()).isEqualTo("foo");

UnresolvedScopedCredentialHelper helper2 =
UnresolvedScopedCredentialHelperConverter.INSTANCE.convert("example.com=foo");
assertThat(helper2.getScope()).hasValue("example.com");
assertThat(helper2.getPath()).isEqualTo("foo");

UnresolvedScopedCredentialHelper helper3 =
UnresolvedScopedCredentialHelperConverter.INSTANCE.convert("*.example.com=foo");
assertThat(helper3.getScope()).hasValue("*.example.com");
assertThat(helper3.getPath()).isEqualTo("foo");
}

@Test
public void emptyPath() {
assertThrows(
OptionsParsingException.class,
() -> UnresolvedScopedCredentialHelperConverter.INSTANCE.convert(""));
assertThrows(
OptionsParsingException.class,
() -> UnresolvedScopedCredentialHelperConverter.INSTANCE.convert("foo="));
assertThrows(
OptionsParsingException.class,
() -> UnresolvedScopedCredentialHelperConverter.INSTANCE.convert("="));
}

@Test
public void emptyScope() {
assertThrows(
OptionsParsingException.class,
() -> UnresolvedScopedCredentialHelperConverter.INSTANCE.convert("=/foo"));
assertThrows(
OptionsParsingException.class,
() -> UnresolvedScopedCredentialHelperConverter.INSTANCE.convert("="));
}
}
1 change: 1 addition & 0 deletions src/test/java/com/google/devtools/build/lib/remote/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ java_test(
"//src/main/java/com/google/devtools/build/lib/analysis:server_directories",
"//src/main/java/com/google/devtools/build/lib/analysis/platform:platform_utils",
"//src/main/java/com/google/devtools/build/lib/authandtls",
"//src/main/java/com/google/devtools/build/lib/authandtls/credentialhelper",
"//src/main/java/com/google/devtools/build/lib/buildeventstream",
"//src/main/java/com/google/devtools/build/lib/clock",
"//src/main/java/com/google/devtools/build/lib/collect/nestedset",
Expand Down
Loading

0 comments on commit aa94b1b

Please sign in to comment.