Skip to content

Commit

Permalink
Terraform login protocol (#82)
Browse files Browse the repository at this point in the history
  • Loading branch information
alfespa17 authored Oct 27, 2021
1 parent b903cbd commit 3854aa4
Show file tree
Hide file tree
Showing 15 changed files with 244 additions and 8 deletions.
1 change: 0 additions & 1 deletion api-job/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
<name>Terrakube Schedule Job</name>
<description>Spring Boot Terrakube schedule job</description>
<properties>
<revision>1.5.0-beta.1</revision>
<java.version>11</java.version>
<okhttp.version>4.9.1</okhttp.version>
<api-client-starter.version>0.7.0-beta.1</api-client-starter.version>
Expand Down
27 changes: 25 additions & 2 deletions api-registry/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<name>Terrakube Terraform Registry</name>
<description>Open Source Terraform Registry for AZB Server</description>
<properties>
<revision>1.5.0-beta.1</revision>
<azure.version>3.9.0</azure.version>
<java.version>11</java.version>
<lombok.version>1.18.20</lombok.version>
<api-client-starter.version>0.6.0</api-client-starter.version>
Expand Down Expand Up @@ -67,6 +67,19 @@
<artifactId>azure-storage-blob</artifactId>
<version>${azure-storage-blob.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>azure-spring-boot-starter-active-directory</artifactId>
</dependency>
<dependency>
<groupId>org.mock-server</groupId>
<artifactId>mockserver-spring-test-listener</artifactId>
Expand All @@ -91,5 +104,15 @@
<scope>test</scope>
</dependency>
</dependencies>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>azure-spring-boot-bom</artifactId>
<version>${azure.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,7 @@
public class OpenRegistryProperties {

private String hostname;
private String clientId;
private String tenantId;
private String scope;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.azbuilder.registry.configuration.security.authentication.azure;

import com.azure.spring.aad.webapi.AADResourceServerWebSecurityConfigurerAdapter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@ConditionalOnProperty(prefix = "org.azbuilder.api.authentication", name = "type", havingValue = "AZURE")
public class AADOAuth2ResourceServerSecurityConfig extends AADResourceServerWebSecurityConfigurerAdapter {
/**
* Add configuration logic as needed.
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
//http.authorizeRequests(requests -> requests.anyRequest().authenticated());
http.authorizeRequests()
.antMatchers("/.well-known/**").permitAll()
.and()
.authorizeRequests()
.anyRequest()
.authenticated();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.azbuilder.registry.configuration.security.authentication.local;

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
@ConditionalOnProperty(prefix = "org.azbuilder.api.authentication", name = "type", havingValue = "LOCAL")
public class LocalWebSecurityAdapter extends WebSecurityConfigurerAdapter {

@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/**");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.azbuilder.registry.controller;

import lombok.AllArgsConstructor;
import org.azbuilder.registry.controller.model.ReadMe;
import org.azbuilder.registry.service.module.ModuleService;
import org.azbuilder.registry.service.readme.ReadMeServiceImpl;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@AllArgsConstructor
@RestController
@RequestMapping("/terraform/readme/v1")
public class ReadMeWebServiceImpl {

ModuleService moduleService;
ReadMeServiceImpl readMeService;

@GetMapping(value = "/{organization}/{module}/{provider}/{version}/download", produces = "application/json")
public ResponseEntity<ReadMe> getModuleVersionPath(@PathVariable String organization, @PathVariable String module, @PathVariable String provider, @PathVariable String version) {
ReadMe readMe = new ReadMe();
String moduleURL = moduleService.getModuleVersionPath(organization, module, provider, version);
readMe.setUrl(moduleURL);
readMe.setContent(readMeService.getContent(moduleURL));
return ResponseEntity.ok().body(readMe);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,31 @@ public class WellKnownWebServiceImpl {

private static final String terraformJsonContent = "{\n" +
" \"modules.v1\": \"%s/terraform/modules/v1/\"\n," +
" \"providers.v1\": \"%s/terraform/providers/v1/\"" +
" \"providers.v1\": \"%s/terraform/providers/v1/\"," +
" \"login.v1\": {\n" +
" \"client\": \"%s\",\n" +
" \"grant_types\": [\"authz_code\", \"%s\"],\n" +
" \"authz\": \"https://login.microsoftonline.com/%s/oauth2/v2.0/authorize?scope=%s\",\n" +
" \"token\": \"https://login.microsoftonline.com/%s/oauth2/v2.0/token\",\n" +
" \"ports\": [10000, 10001]\n" +
" }"+
"}";

@Autowired
OpenRegistryProperties openRegistryProperties;

@GetMapping(produces = "application/json")
public ResponseEntity<String> terraformJson() {
return ResponseEntity.ok(String.format(terraformJsonContent, openRegistryProperties.getHostname(), openRegistryProperties.getHostname()));
return ResponseEntity.ok(
String.format(terraformJsonContent,
openRegistryProperties.getHostname(),
openRegistryProperties.getHostname(),
openRegistryProperties.getClientId(),
openRegistryProperties.getScope(),
openRegistryProperties.getTenantId(),
openRegistryProperties.getScope(),
openRegistryProperties.getTenantId()
)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.azbuilder.registry.controller.model;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class ReadMe {
private String content;
private String url;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package org.azbuilder.registry.service.readme;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.springframework.stereotype.Service;
import org.zeroturnaround.zip.ZipUtil;

import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.UUID;

@AllArgsConstructor
@Slf4j
@Service
public class ReadMeServiceImpl {

private static final String README_DIRECTORY = "/.terraform-spring-boot/readme/";

public String getContent(String moduleURL) {
String readmeText = new String(Base64.getEncoder().encode("NO README FILE".getBytes(StandardCharsets.UTF_8)));
String userHomeDirectory = FileUtils.getUserDirectoryPath();
String gitModulePath = userHomeDirectory.concat(
FilenameUtils.separatorsToSystem(
README_DIRECTORY + "/" + UUID.randomUUID()
));
File gitModuleFolder = new File(gitModulePath);

try {
FileUtils.forceMkdir(gitModuleFolder);
FileUtils.cleanDirectory(gitModuleFolder);

File gitModuleZip = new File(gitModuleFolder.getAbsolutePath() + "/module.zip");
FileUtils.copyURLToFile(new URL(moduleURL), gitModuleZip);

ZipUtil.unpack(gitModuleZip, gitModuleFolder);

File readmeFile = new File(gitModuleFolder.getAbsolutePath() + "/README.md");
readmeText = readFromInputStream(new FileInputStream(readmeFile));

readmeText = new String(Base64.getEncoder().encode(readmeText.getBytes(StandardCharsets.UTF_8)));

FileUtils.cleanDirectory(gitModuleFolder);
if (gitModuleFolder.delete())
log.info("Temp folder deleted...");

} catch (IOException e) {
log.error(e.getMessage());
}

return readmeText;
}

private String readFromInputStream(InputStream inputStream) throws IOException {
StringBuilder resultStringBuilder = new StringBuilder();
try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream))) {
String line;
while ((line = br.readLine()) != null) {
resultStringBuilder.append(line).append("\n");
}
}
return resultStringBuilder.toString();
}

}
23 changes: 23 additions & 0 deletions api-registry/src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -1,13 +1,36 @@
server.port=8075

##################################
#/.well-known/terraform.json Data#
##################################
org.azbuilder.registry.hostname=${AzBuilderRegistry}
org.azbuilder.registry.clientId=${AzureAdAppClientId}
org.azbuilder.registry.tenantid=${AzureAdAppTenantId}
org.azbuilder.registry.scope=${AzureAdAppScope}

#####################
#Authentication Type#
#####################
org.azbuilder.api.authentication.type=${AuthenticationValidationTypeRegistry}

#######################################
#AZURE ACTIVE DIRECTORY AUTHENTICATION#
#######################################
azure.activedirectory.client-id=${AzureAdAppId}
azure.activedirectory.app-id-uri=${AzureAdApiIdUri}

##################
#Terrakube Client#
##################
org.azbuilder.api.url=${AzBuilderApiUrl}
org.azbuilder.api.clientId=${AzureAdAppClientId}
org.azbuilder.api.clientSecret=${AzureAdAppClientSecret}
org.azbuilder.api.tenantId=${AzureAdAppTenantId}
org.azbuilder.api.scope=${AzureAdAppScope}

#################
#Storage Service#
#################
org.azbuilder.registry.plugin.storage.type=AzureStorageImpl
org.azbuilder.registry.plugin.storage.azure.accountName=${AzureAccountName}
org.azbuilder.registry.plugin.storage.azure.accountKey=${AzureAccountKey}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,14 @@ public class WellKnownTests extends OpenRegistryApplicationTests{

private static final String WELL_KNOWN_RESPONSE="{\n" +
" \"modules.v1\": \"http://localhost/terraform/modules/v1/\"\n," +
" \"providers.v1\": \"http://localhost/terraform/providers/v1/\"" +
" \"providers.v1\": \"http://localhost/terraform/providers/v1/\"," +
" \"login.v1\": {\n" +
" \"client\": \"sample\",\n" +
" \"grant_types\": [\"authz_code\", \"sample\"],\n" +
" \"authz\": \"https://login.microsoftonline.com/sample/oauth2/v2.0/authorize?scope=sample\",\n" +
" \"token\": \"https://login.microsoftonline.com/sample/oauth2/v2.0/token\",\n" +
" \"ports\": [10000, 10001]\n" +
" }"+
"}";

@Test
Expand Down
6 changes: 6 additions & 0 deletions api-registry/src/test/resources/application-test.properties
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ org.azbuilder.api.url=http://localhost:9999
#org.azbuilder.api.tenantId=${AzureAdAppTenantId}
#org.azbuilder.api.scope=${AzureAdAppScope}

org.azbuilder.registry.clientId=sample
org.azbuilder.registry.tenantid=sample
org.azbuilder.registry.scope=sample

org.azbuilder.api.authentication.type=LOCAL

org.azbuilder.registry.plugin.storage.type=Local
#org.azbuilder.registry.plugin.storage.azure.accountName=${AzureAccountName}
#org.azbuilder.registry.plugin.storage.azure.accountKey=${AzureAccountKey}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/callback/v1/**").permitAll()
.antMatchers("/doc").permitAll()
.anyRequest().authenticated();
.and()
.authorizeRequests()
.anyRequest()
.authenticated();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public class Workspace {
@OneToMany(mappedBy = "workspace")
private List<Variable> variable;

@UpdatePermission(expression = "user is a service")
@OneToMany(mappedBy = "workspace")
private List<History> history;

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<packaging>pom</packaging>

<properties>
<revision>1.5.0-beta.1</revision>
<revision>1.5.0-beta.2</revision>
<sonar.organization>azbuilder</sonar.organization>
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
<sonar.project.key>AzBuilder_azb-server</sonar.project.key>
Expand Down

0 comments on commit 3854aa4

Please sign in to comment.