Skip to content
252 changes: 218 additions & 34 deletions README.adoc

Large diffs are not rendered by default.

12 changes: 7 additions & 5 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
buildscript {
ext {
springBoot_1_X_Version = '1.5.13.RELEASE'
springBoot_2_X_Version = '2.1.3.RELEASE'
grpcVersion = '1.31.1'
springBoot_2_X_Version = '2.3.3.RELEASE'
grpcVersion = '1.32.1'
}
repositories {
mavenCentral()
Expand Down Expand Up @@ -39,6 +38,8 @@ allprojects {
mavenCentral()
jcenter()
maven { url "https://repo.spring.io/milestone" }
maven { url "https://jitpack.io" }

}
}

Expand Down Expand Up @@ -69,7 +70,8 @@ subprojects {
task codeCoverageReport(type: JacocoReport) {
executionData fileTree(project.rootDir.absolutePath).include("**/build/jacoco/*.exec")

sourceSets project('grpc-spring-boot-starter').sourceSets.main
sourceSets (project('grpc-spring-boot-starter').sourceSets.main
,project('grpc-client-spring-boot-starter').sourceSets.main)

//subprojects.each {
//sourceSets it.sourceSets.main
Expand All @@ -78,7 +80,7 @@ task codeCoverageReport(type: JacocoReport) {
reports {
xml.enabled true
xml.destination = new File(buildDir,"reports/jacoco/report.xml")
html.enabled false
html.enabled true
csv.enabled false
}
}
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version=3.5.8-SNAPSHOT
version=4.0.0-SNAPSHOT
group=io.github.lognet
description=Spring Boot starter for Google RPC.
gitHubUrl=https\://github.com/LogNet/grpc-spring-boot-starter
Expand Down
119 changes: 119 additions & 0 deletions grpc-client-spring-boot-starter/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
buildscript {
repositories {
gradlePluginPortal()
mavenCentral()
}
dependencies {

classpath "io.franzbecker:gradle-lombok:4.0.0"
}
}

apply plugin: 'java'
apply plugin: 'maven-publish'
apply plugin: 'signing'
apply plugin: "de.marcphilipp.nexus-publish"
apply plugin: 'io.franzbecker.gradle-lombok'

task delombok(type: io.franzbecker.gradle.lombok.task.DelombokTask) {
def outputDir = file("$buildDir/delombok")
outputs.dir(outputDir)
for (srcDir in project.sourceSets.main.java.srcDirs) {
inputs.dir(srcDir)
args(srcDir, "-d", outputDir)
}
doFirst {
outputDir.deleteDir()
}
}

task sourceJar(type: Jar) {
classifier "sources"
from delombok
}

task javadocJar(type: Jar, dependsOn: javadoc) {
classifier "javadoc"
from javadoc.destinationDir
}

artifacts {
archives jar
archives sourceJar
archives javadocJar
}
signing {
sign configurations.archives
}


nexusPublishing {
clientTimeout = java.time.Duration.ofMinutes(7)
repositories {
sonatype()
}

}

publishing {
publications {
mavenJava(MavenPublication) {
pom {
name = 'grpc-spring-boot-starter'
description = 'grpc-spring-boot-starter'
url = 'https://github.com/LogNet/grpc-spring-boot-starter'

scm {
url = 'https://github.com/LogNet/grpc-spring-boot-starter'
connection = 'scm:https://LogNet@github.com/LogNet/grpc-spring-boot-starter.git'
developerConnection = 'scm:git://github.com/LogNet/grpc-spring-boot-starter.git'
}

licenses {
license {
name = 'The Apache Software License, Version 2.0'
url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
distribution = 'repo'
}
}

developers {
developer {
id = 'jvmlet'
name = 'Furer Alexander'
email = 'furer.alexander@gmail.com'
}
}

}

from components.java


artifact(sourceJar) {
classifier = 'sources'
}
artifact(javadocJar) {
classifier = 'javadoc'
}
}
}
}

signing {
required {
// signing is required if this is a release version and the artifacts are to be published
!version.toString().endsWith('-SNAPSHOT') && tasks.withType(PublishToMavenRepository).find {
gradle.taskGraph.hasTask it
}
}
sign publishing.publications
}


dependencies {
compile "io.grpc:grpc-api:${grpcVersion}"
}
compileJava.dependsOn(processResources)


Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package org.lognet.springboot.grpc.security;

import io.grpc.CallCredentials;
import io.grpc.Metadata;
import io.grpc.Status;

import java.util.concurrent.Executor;

/**
* Adds Authorization header with configured configured authentication scheme token supplied by tokeSupplier
*/

public class AuthCallCredentials extends CallCredentials {
private AuthHeader authHeader;

public AuthCallCredentials(AuthHeader.AuthHeaderBuilder authHeaderBuilder) {
this(authHeaderBuilder.build());
}
public AuthCallCredentials(AuthHeader authHeader) {
this.authHeader = authHeader;
}

@Override
public void applyRequestMetadata(RequestInfo requestInfo, Executor appExecutor, MetadataApplier metadataApplier) {

appExecutor.execute(()->{
try {
metadataApplier.apply(authHeader.attach(new Metadata()));
} catch (Throwable e) {
metadataApplier.fail(Status.UNAUTHENTICATED.withCause(e));
}
}
);



}

@Override
public void thisUsesUnstableApi() {
// noop
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.lognet.springboot.grpc.security;

import io.grpc.CallOptions;
import io.grpc.Channel;
import io.grpc.ClientCall;
import io.grpc.ClientInterceptor;
import io.grpc.ClientInterceptors;
import io.grpc.Metadata;
import io.grpc.MethodDescriptor;

/**
* Adds Authorization header with configured authentication scheme token supplied by tokeSupplier to each intercepted client call
*/


public class AuthClientInterceptor implements ClientInterceptor {
private AuthHeader authHeader;

public AuthClientInterceptor(AuthHeader authHeader) {
this.authHeader = authHeader;
}
public AuthClientInterceptor(AuthHeader.AuthHeaderBuilder authHeaderBuilder) {
this(authHeaderBuilder.build());
}

@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> methodDescriptor, CallOptions callOptions, Channel next) {
return new ClientInterceptors.CheckedForwardingClientCall<ReqT, RespT>(next.newCall(methodDescriptor, callOptions)) {
@Override
protected void checkedStart(Listener<RespT> responseListener, Metadata headers) throws Exception {
delegate().start(responseListener, authHeader.attach(headers));
}
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package org.lognet.springboot.grpc.security;

import io.grpc.Metadata;
import lombok.Builder;

import java.nio.ByteBuffer;
import java.util.Base64;
import java.util.function.Supplier;

@Builder
public class AuthHeader implements Constants {
private final Supplier<ByteBuffer> tokenSupplier;
private final String authScheme;

public static class AuthHeaderBuilder {

public AuthHeader.AuthHeaderBuilder bearer() {
return authScheme(Constants.BEARER_AUTH_SCHEME);
}
public AuthHeader.AuthHeaderBuilder basic() {
return authScheme(Constants.BASIC_AUTH_SCHEME);
}

public AuthHeader.AuthHeaderBuilder basic(String userName, byte[] password) {
final ByteBuffer buffer = ByteBuffer.allocate(userName.length() + password.length + 1)
.put(userName.getBytes())
.put((byte) ':')
.put(password);
buffer.rewind();
ByteBuffer token = Base64.getEncoder().encode(buffer);
return authScheme(Constants.BASIC_AUTH_SCHEME)
.tokenSupplier(() -> {
token.rewind();
return token;
});
}


}
public Metadata attach(Metadata metadataHeader){
byte[] token = tokenSupplier.get().array();
final byte[] header = ByteBuffer.allocate(authScheme.length() + token.length + 1)
.put(authScheme.getBytes())
.put((byte) ' ')
.put(token)
.array();
metadataHeader.put(Constants.AUTH_HEADER_KEY,header);
return metadataHeader;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.lognet.springboot.grpc.security;

import io.grpc.Metadata;


public interface Constants {
Metadata.Key<byte[]> AUTH_HEADER_KEY = Metadata.Key.of("Authorization"+Metadata.BINARY_HEADER_SUFFIX, Metadata.BINARY_BYTE_MARSHALLER);
String BEARER_AUTH_SCHEME="Bearer";
String BASIC_AUTH_SCHEME="Basic";



}
36 changes: 32 additions & 4 deletions grpc-spring-boot-starter-demo/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,51 @@ buildscript {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBoot_1_X_Version}")
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBoot_2_X_Version}")
}
}
apply plugin: 'java'
apply plugin: 'com.google.protobuf'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
ext {
set('springCloudVersion', "Hoxton.SR6")

}
dependencies {

compile "org.springframework.boot:spring-boot-starter-actuator"
compile 'org.springframework.boot:spring-boot-starter-web'

compile "org.springframework.security:spring-security-config"
compile "org.springframework.security:spring-security-oauth2-jose"
compile "org.springframework.security:spring-security-oauth2-resource-server"


compile project(':grpc-spring-boot-starter')
compile project(':grpc-client-spring-boot-starter')

testCompile 'org.springframework.boot:spring-boot-starter-aop'
testCompile 'org.springframework.boot:spring-boot-starter-test'
testCompile 'com.github.stefanbirkner:system-rules:1.18.0'
testCompile('org.springframework.cloud:spring-cloud-starter-consul-discovery')
testCompile 'com.pszymczyk.consul:embedded-consul:2.1.4'

testCompile "org.springframework.cloud:spring-cloud-config-server:2.1.1.RELEASE"
testCompile "org.springframework.cloud:spring-cloud-config-client:2.1.1.RELEASE"
testCompile "com.playtika.testcontainers:embedded-keycloak:1.76"
testRuntime "org.springframework.cloud:spring-cloud-starter"



testImplementation 'org.hamcrest:hamcrest:2.1'

testImplementation 'org.mockito:mockito-core:2.23.0'



//testCompile "org.testcontainers:junit-jupiter:1.14.3"

}
sourceSets {
main {
Expand Down Expand Up @@ -63,16 +91,16 @@ task cleanProtoGen{
}
}
clean.dependsOn cleanProtoGen
bootRepackage.enabled =false


dependencyManagement {
imports {
mavenBom "org.springframework.boot:spring-boot-starter-parent:${springBoot_1_X_Version}"
mavenBom "org.springframework.boot:spring-boot-starter-parent:${springBoot_2_X_Version}"
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}






Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,11 @@
import io.grpc.examples.CalculatorOuterClass;
import io.grpc.stub.StreamObserver;
import org.lognet.springboot.grpc.GRpcService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DemoAppConfiguration {
@Bean
public GreeterService greeterService() {
return new GreeterService();
}


@GRpcService(interceptors = NotSpringBeanInterceptor.class)
public static class CalculatorService extends CalculatorGrpc.CalculatorImplBase{
Expand Down
Loading