com.google.jenkins.plugins.credentials.oauth.GoogleRobotPrivateKeyCredentialsTest.java Source code

Java tutorial

Introduction

Here is the source code for com.google.jenkins.plugins.credentials.oauth.GoogleRobotPrivateKeyCredentialsTest.java

Source

/*
 * Copyright 2013 Google Inc. 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.jenkins.plugins.credentials.oauth;

import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.security.KeyPair;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import org.apache.commons.fileupload.FileItem;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import com.cloudbees.plugins.credentials.CredentialsScope;
import com.cloudbees.plugins.credentials.SystemCredentialsProvider;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.HttpStatusCodes;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.testing.http.MockHttpTransport;
import com.google.api.client.testing.http.MockLowLevelHttpRequest;
import com.google.api.client.testing.http.MockLowLevelHttpResponse;
import hudson.util.FormValidation;
import jenkins.model.Jenkins;

/**
 * Tests for {@link GoogleRobotPrivateKeyCredentials}.
 */
public class GoogleRobotPrivateKeyCredentialsTest {
    private static final String SERVICE_ACCOUNT_EMAIL_ADDRESS = "service@account.com";
    private static final String ACCESS_TOKEN = "ThE.ToKeN";
    private static final String PROJECT_ID = "foo.com:bar-baz";
    private static final String FAKE_SCOPE = "my.fake.scope";
    private static KeyPair keyPair;
    private static String jsonKeyPath;
    private static String p12KeyPath;
    private static String legacyJsonKeyPath;
    @Rule
    public JenkinsRule jenkins = new JenkinsRule();
    private MockHttpTransport transport;
    private MockLowLevelHttpRequest request;
    @Mock
    private FileItem mockFileItem;
    @Mock
    private GoogleCredential credential;
    private GoogleRobotCredentialsModule module;

    @BeforeClass
    public static void preparePrivateKey() throws Exception {
        keyPair = P12ServiceAccountConfigTestUtil.generateKeyPair();
        jsonKeyPath = JsonServiceAccountConfigTestUtil.createTempJsonKeyFile(SERVICE_ACCOUNT_EMAIL_ADDRESS,
                keyPair.getPrivate());
        p12KeyPath = P12ServiceAccountConfigTestUtil.createTempP12KeyFile(keyPair);
        legacyJsonKeyPath = LegacyJsonServiceAccountConfigUtil
                .createTempLegacyJsonKeyFile(SERVICE_ACCOUNT_EMAIL_ADDRESS);
    }

    private static void setPrivateField(GoogleRobotPrivateKeyCredentials credentials, String fieldName,
            Object value) throws NoSuchFieldException, IllegalAccessException {
        Field field = GoogleRobotPrivateKeyCredentials.class.getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(credentials, value);
    }

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        transport = spy(new MockHttpTransport());
        request = spy(new MockLowLevelHttpRequest());

        module = new GoogleRobotCredentialsModule() {
            @Override
            public HttpTransport getHttpTransport() {
                return transport;
            }
        };
    }

    @Test
    public void testCreatePrivateKeyCredentialsWithJsonKeyType() throws Exception {
        when(mockFileItem.getSize()).thenReturn(1L);
        when(mockFileItem.getInputStream()).thenReturn(new FileInputStream(jsonKeyPath));
        GoogleRobotPrivateKeyCredentials credentials = new GoogleRobotPrivateKeyCredentials(PROJECT_ID,
                new JsonServiceAccountConfig(mockFileItem, null), module);

        assertEquals(CredentialsScope.GLOBAL, credentials.getScope());
        assertEquals(SERVICE_ACCOUNT_EMAIL_ADDRESS, credentials.getUsername());

        GoogleCredential googleCredential = credentials
                .getGoogleCredential(new TestGoogleOAuth2DomainRequirement(FAKE_SCOPE));
        assertNotNull(googleCredential);

        stubRequest("https://accounts.google.com/o/oauth2/token", HttpStatusCodes.STATUS_CODE_OK,
                "{\"access_token\":\"" + ACCESS_TOKEN + "\"," + "\"expires_in\":1234,"
                        + "\"token_type\":\"Bearer\"}");

        try {
            assertTrue(googleCredential.refreshToken());
            assertEquals(ACCESS_TOKEN, googleCredential.getAccessToken());
        } finally {
            verifyRequest("https://accounts.google.com/o/oauth2/token");
        }
    }

    @Test
    public void testCreatePrivateKeyCredentialsWithP12KeyType() throws Exception {
        when(mockFileItem.getSize()).thenReturn(1L);
        when(mockFileItem.getInputStream()).thenReturn(new FileInputStream(p12KeyPath));
        P12ServiceAccountConfig keyType = new P12ServiceAccountConfig(SERVICE_ACCOUNT_EMAIL_ADDRESS, mockFileItem,
                null);
        GoogleRobotPrivateKeyCredentials credentials = new GoogleRobotPrivateKeyCredentials(PROJECT_ID, keyType,
                module);

        assertEquals(CredentialsScope.GLOBAL, credentials.getScope());
        assertEquals(SERVICE_ACCOUNT_EMAIL_ADDRESS, credentials.getUsername());

        GoogleCredential googleCredential = credentials
                .getGoogleCredential(new TestGoogleOAuth2DomainRequirement(FAKE_SCOPE));
        assertNotNull(googleCredential);

        stubRequest("https://accounts.google.com/o/oauth2/token", HttpStatusCodes.STATUS_CODE_OK,
                "{\"access_token\":\"" + ACCESS_TOKEN + "\"," + "\"expires_in\":1234,"
                        + "\"token_type\":\"Bearer\"}");

        try {
            assertTrue(googleCredential.refreshToken());
            assertEquals(ACCESS_TOKEN, googleCredential.getAccessToken());
        } finally {
            verifyRequest("https://accounts.google.com/o/oauth2/token");
        }
    }

    private void stubRequest(String url, int statusCode, String responseContent) throws IOException {
        request.setResponse(new MockLowLevelHttpResponse().setStatusCode(statusCode).setContent(responseContent));
        doReturn(request).when(transport).buildRequest("POST", url);
    }

    private void verifyRequest(String url) throws IOException {
        verify(transport).buildRequest("POST", url);
        verify(request).execute();
    }

    @Test
    public void testCreatePrivateKeyCredentialsWithNullKeyType() throws Exception {
        GoogleRobotPrivateKeyCredentials credentials = new GoogleRobotPrivateKeyCredentials(PROJECT_ID, null,
                module);

        try {
            credentials.getUsername();
            fail();
        } catch (GoogleRobotPrivateKeyCredentials.KeyTypeNotSetException ignored) {
        }

        try {
            credentials.getGoogleCredential(new TestGoogleOAuth2DomainRequirement(FAKE_SCOPE));
            fail();
        } catch (GoogleRobotPrivateKeyCredentials.KeyTypeNotSetException ignored) {
        }
    }

    @Test
    public void testUpgradeLegacyCredentials() throws Exception {
        GoogleRobotPrivateKeyCredentials legacyCredentials = new GoogleRobotPrivateKeyCredentials(PROJECT_ID, null,
                null);
        setPrivateField(legacyCredentials, "secretsFile", legacyJsonKeyPath);
        setPrivateField(legacyCredentials, "p12File", p12KeyPath);
        GoogleRobotPrivateKeyCredentials upgradedCredentials = (GoogleRobotPrivateKeyCredentials) legacyCredentials
                .readResolve();

        assertEquals(SERVICE_ACCOUNT_EMAIL_ADDRESS, upgradedCredentials.getUsername());
        GoogleCredential googleCredential = upgradedCredentials
                .getGoogleCredential(new TestGoogleOAuth2DomainRequirement(FAKE_SCOPE));
        assertEquals(keyPair.getPrivate(), googleCredential.getServiceAccountPrivateKey());
    }

    @Test
    public void testUpgradeLegacyCredentialsWithoutSecretsFile() throws Exception {
        GoogleRobotPrivateKeyCredentials legacyCredentials = new GoogleRobotPrivateKeyCredentials(PROJECT_ID, null,
                null);
        setPrivateField(legacyCredentials, "p12File", p12KeyPath);
        GoogleRobotPrivateKeyCredentials upgradedCredentials = (GoogleRobotPrivateKeyCredentials) legacyCredentials
                .readResolve();

        try {
            upgradedCredentials.getUsername();
            fail();
        } catch (GoogleRobotPrivateKeyCredentials.AccountIdNotSetException ignored) {
        }
        try {
            upgradedCredentials.getGoogleCredential(new TestGoogleOAuth2DomainRequirement(FAKE_SCOPE));
            fail();
        } catch (GoogleRobotPrivateKeyCredentials.AccountIdNotSetException ignored) {
        }
    }

    @Test
    public void testUpgradeLegacyCredentialsWithMissingWebObject() throws Exception {
        String legacyJsonKeyFileWithMissingWebObject = LegacyJsonServiceAccountConfigUtil
                .createTempLegacyJsonKeyFileWithMissingWebObject();
        GoogleRobotPrivateKeyCredentials legacyCredentials = new GoogleRobotPrivateKeyCredentials(PROJECT_ID, null,
                null);
        setPrivateField(legacyCredentials, "secretsFile", legacyJsonKeyFileWithMissingWebObject);
        setPrivateField(legacyCredentials, "p12File", p12KeyPath);
        GoogleRobotPrivateKeyCredentials upgradedCredentials = (GoogleRobotPrivateKeyCredentials) legacyCredentials
                .readResolve();

        try {
            upgradedCredentials.getUsername();
            fail();
        } catch (GoogleRobotPrivateKeyCredentials.AccountIdNotSetException ignored) {
        }
        try {
            upgradedCredentials.getGoogleCredential(new TestGoogleOAuth2DomainRequirement(FAKE_SCOPE));
            fail();
        } catch (GoogleRobotPrivateKeyCredentials.AccountIdNotSetException ignored) {
        }
    }

    @Test
    public void testUpgradeLegacyCredentialsWithMissingClientEmail() throws Exception {
        String legacyJsonKeyFileWithMissingClientEmail = LegacyJsonServiceAccountConfigUtil
                .createTempLegacyJsonKeyFileWithMissingClientEmail();
        GoogleRobotPrivateKeyCredentials legacyCredentials = new GoogleRobotPrivateKeyCredentials(PROJECT_ID, null,
                null);
        setPrivateField(legacyCredentials, "secretsFile", legacyJsonKeyFileWithMissingClientEmail);
        setPrivateField(legacyCredentials, "p12File", p12KeyPath);
        GoogleRobotPrivateKeyCredentials upgradedCredentials = (GoogleRobotPrivateKeyCredentials) legacyCredentials
                .readResolve();

        try {
            upgradedCredentials.getUsername();
            fail();
        } catch (GoogleRobotPrivateKeyCredentials.AccountIdNotSetException ignored) {
        }
        try {
            upgradedCredentials.getGoogleCredential(new TestGoogleOAuth2DomainRequirement(FAKE_SCOPE));
            fail();
        } catch (GoogleRobotPrivateKeyCredentials.AccountIdNotSetException ignored) {
        }
    }

    @Test
    public void testUpgradeLegacyCredentialsWithInvalidSecretsFile() throws Exception {
        String invalidLegacyJsonKeyFile = LegacyJsonServiceAccountConfigUtil.createTempInvalidLegacyJsonKeyFile();
        GoogleRobotPrivateKeyCredentials legacyCredentials = new GoogleRobotPrivateKeyCredentials(PROJECT_ID, null,
                null);
        setPrivateField(legacyCredentials, "secretsFile", invalidLegacyJsonKeyFile);
        setPrivateField(legacyCredentials, "p12File", p12KeyPath);
        GoogleRobotPrivateKeyCredentials upgradedCredentials = (GoogleRobotPrivateKeyCredentials) legacyCredentials
                .readResolve();

        try {
            upgradedCredentials.getUsername();
            fail();
        } catch (GoogleRobotPrivateKeyCredentials.AccountIdNotSetException ignored) {
        }
        try {
            upgradedCredentials.getGoogleCredential(new TestGoogleOAuth2DomainRequirement(FAKE_SCOPE));
            fail();
        } catch (GoogleRobotPrivateKeyCredentials.AccountIdNotSetException ignored) {
        }
    }

    @Test
    public void testUpgradeLegacyCredentialsWithNotExistendSecretsFile() throws Exception {
        GoogleRobotPrivateKeyCredentials legacyCredentials = new GoogleRobotPrivateKeyCredentials(PROJECT_ID, null,
                null);
        setPrivateField(legacyCredentials, "secretsFile", "/notExistendSecretsFile");
        setPrivateField(legacyCredentials, "p12File", p12KeyPath);
        GoogleRobotPrivateKeyCredentials upgradedCredentials = (GoogleRobotPrivateKeyCredentials) legacyCredentials
                .readResolve();

        try {
            upgradedCredentials.getUsername();
            fail();
        } catch (GoogleRobotPrivateKeyCredentials.AccountIdNotSetException ignored) {
        }
        try {
            upgradedCredentials.getGoogleCredential(new TestGoogleOAuth2DomainRequirement(FAKE_SCOPE));
            fail();
        } catch (GoogleRobotPrivateKeyCredentials.AccountIdNotSetException ignored) {
        }
    }

    @Test
    public void testUpgradeLegacyCredentialsWithoutP12File() throws Exception {
        GoogleRobotPrivateKeyCredentials legacyCredentials = new GoogleRobotPrivateKeyCredentials(PROJECT_ID, null,
                null);
        setPrivateField(legacyCredentials, "secretsFile", legacyJsonKeyPath);
        GoogleRobotPrivateKeyCredentials upgradedCredentials = (GoogleRobotPrivateKeyCredentials) legacyCredentials
                .readResolve();

        assertEquals(SERVICE_ACCOUNT_EMAIL_ADDRESS, upgradedCredentials.getUsername());
        try {
            upgradedCredentials.getGoogleCredential(new TestGoogleOAuth2DomainRequirement(FAKE_SCOPE));
            fail();
        } catch (GoogleRobotPrivateKeyCredentials.PrivateKeyNotSetException ignored) {
        }
    }

    @Test
    public void testGetById() throws Exception {
        GoogleRobotPrivateKeyCredentials credentials = new GoogleRobotPrivateKeyCredentials(PROJECT_ID,
                new JsonServiceAccountConfig(mockFileItem, null), null);

        SystemCredentialsProvider.getInstance().getCredentials().add(credentials);

        assertSame(credentials, GoogleRobotCredentials.getById(credentials.getId()));
    }

    // TODO(mattmoor): redundant with GoogleRobotMetadataCredentials since there
    // isn't a shared descriptor for validating common fields.
    @Test
    public void testProjectIdValidation() throws Exception {
        GoogleRobotPrivateKeyCredentials.Descriptor descriptor = (GoogleRobotPrivateKeyCredentials.Descriptor) Jenkins
                .getInstance().getDescriptorOrDie(GoogleRobotPrivateKeyCredentials.class);

        assertEquals(FormValidation.Kind.OK, descriptor.doCheckProjectId(PROJECT_ID).kind);
        assertEquals(FormValidation.Kind.ERROR, descriptor.doCheckProjectId(null).kind);
        assertEquals(FormValidation.Kind.ERROR, descriptor.doCheckProjectId("").kind);
    }

    // TODO(mattmoor): Figure out why this flakes out so much under testing
    // @Test
    // public void testName() throws Exception {
    //   GoogleRobotPrivateKeyCredentials credentials =
    //       new GoogleRobotPrivateKeyCredentials(PROJECT_ID, "", mockFileItem,
    //           "", mockFileItem, null /* module */);
    //   SystemCredentialsProvider.getInstance().getCredentials()
    //      .add(credentials);

    //   assertEquals(PROJECT_ID, CredentialsNameProvider.name(credentials));
    //   assertEquals(PROJECT_ID, new GoogleRobotNameProvider().getName(
    //       credentials));
    // }
}