Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Access token connection #230

Merged
merged 7 commits into from Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions RMQClient.xcodeproj/project.pbxproj
Expand Up @@ -9,6 +9,7 @@
/* Begin PBXBuildFile section */
1029A0E22087A97E00C72924 /* ConnectionDeadlockTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1029A0E12087A97E00C72924 /* ConnectionDeadlockTests.swift */; };
4DF6E46D27F6E98100C43208 /* RMQClient.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AEE7FE911C3BCA6000DF8C4F /* RMQClient.framework */; };
5CE0C5292B873842000087B7 /* ConnectionUpdateSecretTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CE0C5282B873842000087B7 /* ConnectionUpdateSecretTest.swift */; };
70311B0B21ED538600AE1804 /* RMQConnectionDefaults.h in Headers */ = {isa = PBXBuildFile; fileRef = 70311B0A21ED538600AE1804 /* RMQConnectionDefaults.h */; };
70338A2421FBAA7C00C9069D /* TLSConnectionIntegrationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70338A2321FBAA7C00C9069D /* TLSConnectionIntegrationTest.swift */; };
705359A921D174A400CF6456 /* TestCertificates in Resources */ = {isa = PBXBuildFile; fileRef = 705359A821D174A400CF6456 /* TestCertificates */; };
Expand Down Expand Up @@ -238,6 +239,7 @@
/* Begin PBXFileReference section */
1029A0E12087A97E00C72924 /* ConnectionDeadlockTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConnectionDeadlockTests.swift; sourceTree = "<group>"; };
4DF6E43627F6E90700C43208 /* MemoryTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MemoryTest.app; sourceTree = BUILT_PRODUCTS_DIR; };
5CE0C5282B873842000087B7 /* ConnectionUpdateSecretTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectionUpdateSecretTest.swift; sourceTree = "<group>"; };
70311B0A21ED538600AE1804 /* RMQConnectionDefaults.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RMQConnectionDefaults.h; sourceTree = "<group>"; };
70338A2321FBAA7C00C9069D /* TLSConnectionIntegrationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TLSConnectionIntegrationTest.swift; sourceTree = "<group>"; };
705359A821D174A400CF6456 /* TestCertificates */ = {isa = PBXFileReference; lastKnownFileType = folder; path = TestCertificates; sourceTree = SOURCE_ROOT; };
Expand Down Expand Up @@ -491,6 +493,7 @@
AE26FA2F1C970E9A00CDBBAA /* Channels */ = {
isa = PBXGroup;
children = (
5CE0C5282B873842000087B7 /* ConnectionUpdateSecretTest.swift */,
AE26FA2D1C970DF100CDBBAA /* RMQChannelContract.swift */,
AE8279841C8D86110013ADD1 /* ChannelAllocationTest.swift */,
AE8AD2681CC545ED00229444 /* RMQFramesetValidatorTest.swift */,
Expand Down Expand Up @@ -1292,6 +1295,7 @@
AE9DB00D1D12AA120005F44B /* RMQTransactionalConfirmationsTest.swift in Sources */,
AE11F1B21D155C8A007AD330 /* RMQMessageTest.swift in Sources */,
AE9DB0091D11FDED0005F44B /* ConfirmationsSpy.swift in Sources */,
5CE0C5292B873842000087B7 /* ConnectionUpdateSecretTest.swift in Sources */,
AEA8A7621CC97C7900371E38 /* RMQGCDSerialQueueTest.swift in Sources */,
AE59345B1C8735FA00560A73 /* ChannelSpy.swift in Sources */,
AE8AD25C1CC4E67F00229444 /* RMQUnallocatedChannelTest.swift in Sources */,
Expand Down
10 changes: 10 additions & 0 deletions RMQClient/RMQConnection.h
Expand Up @@ -242,4 +242,14 @@
*/
- (nonnull id<RMQChannel>)createChannel;

/*!
* @brief Update secret.
* This method updates the secret used to authenticate this connection.
* It is used when secrets have an expiration date and need to be renewed, like OAuth 2 tokens.
* @param secret The new secret.
* @param reason The reason for the secret update.
*/
- (void)updateSecret:(nonnull NSString *)secret
reason:(nonnull NSString *)reason;

@end
16 changes: 16 additions & 0 deletions RMQClient/RMQConnection.m
Expand Up @@ -608,6 +608,14 @@ - (void)start {
return ch;
}

- (void)updateSecret:(NSString *)secret
reason:(NSString *)reason
{
[self.commandQueue enqueue:^{
[self sendFrameset:[[RMQFrameset alloc] initWithChannelNumber:@0 method:[self methodForUpdateSecret:secret reason:reason]]];
}];
}

- (BOOL)hasCompletedHandshake {
return self.handshakeComplete;
}
Expand Down Expand Up @@ -746,6 +754,14 @@ - (void)closeAllUserChannels {
}
}

- (RMQConnectionUpdateSecret *)methodForUpdateSecret:(NSString *)secret
reason:(NSString *)reason {
RMQLongstr *secretLongstr = [[RMQLongstr alloc] init:secret];
RMQShortstr *reasonShortstr = [[RMQShortstr alloc] init:reason];
return [[RMQConnectionUpdateSecret alloc] initWithSecret:secretLongstr
reason:reasonShortstr];
}

- (RMQConnectionClose *)amqClose {
return [[RMQConnectionClose alloc] initWithReplyCode:[[RMQShort alloc] init:200]
replyText:[[RMQShortstr alloc] init:@"Goodbye"]
Expand Down
2 changes: 2 additions & 0 deletions RMQClient/RMQMethodMap.m
Expand Up @@ -18,6 +18,8 @@ + (NSDictionary *)methodMap {
@[@(10), @(51)] : [RMQConnectionCloseOk class],
@[@(10), @(60)] : [RMQConnectionBlocked class],
@[@(10), @(61)] : [RMQConnectionUnblocked class],
@[@(10), @(70)] : [RMQConnectionUpdateSecret class],
@[@(10), @(71)] : [RMQConnectionUpdateSecretOk class],
@[@(20), @(10)] : [RMQChannelOpen class],
@[@(20), @(11)] : [RMQChannelOpenOk class],
@[@(20), @(20)] : [RMQChannelFlow class],
Expand Down
9 changes: 9 additions & 0 deletions RMQClient/RMQMethods.h
Expand Up @@ -86,6 +86,15 @@ typedef NS_OPTIONS(NSUInteger, RMQConnectionOpenOptions) {
@end
@interface RMQConnectionUnblocked : RMQValue <RMQMethod>

@end
@interface RMQConnectionUpdateSecret : RMQValue <RMQMethod>
@property (nonnull, copy, nonatomic, readonly) RMQLongstr *secret;
@property (nonnull, copy, nonatomic, readonly) RMQShortstr *reason;
- (nonnull instancetype)initWithSecret:(nonnull RMQLongstr *)secret
reason:(nonnull RMQShortstr *)reason;
@end
@interface RMQConnectionUpdateSecretOk : RMQValue <RMQMethod>

@end
@interface RMQChannelOpen : RMQValue <RMQMethod>
@property (nonnull, copy, nonatomic, readonly) RMQShortstr *reserved1;
Expand Down
91 changes: 91 additions & 0 deletions RMQClient/RMQMethods.m
Expand Up @@ -639,6 +639,97 @@ - (NSNumber *)frameTypeID { return @1; }
- (BOOL)hasContent { return NO; }


- (instancetype)initWithDecodedFrame:(NSArray *)frame {
self = [super init];
if (self) {
self.payloadArguments = @[];
}
return self;
}

- (NSData *)amqEncoded {
NSMutableData *encoded = [NSMutableData new];
[encoded appendData:[[RMQShort alloc] init:self.classID.integerValue].amqEncoded];
[encoded appendData:[[RMQShort alloc] init:self.methodID.integerValue].amqEncoded];
for (id<RMQEncodable>arg in self.payloadArguments) {
[encoded appendData:arg.amqEncoded];
}
return encoded;
}

@end

@interface RMQConnectionUpdateSecret ()
@property (nonnull, copy, nonatomic, readwrite) RMQLongstr *secret;
@property (nonnull, copy, nonatomic, readwrite) RMQShortstr *reason;
@property (nonatomic, readwrite) NSArray *payloadArguments;
@property (nonatomic, readwrite) BOOL hasContent;
@end

@implementation RMQConnectionUpdateSecret

+ (NSArray *)propertyClasses {
return @[[RMQLongstr class],
[RMQShortstr class]];
}
- (NSNumber *)classID { return @10; }
- (NSNumber *)methodID { return @70; }
- (Class)syncResponse { return [RMQConnectionUpdateSecretOk class]; }
- (NSNumber *)frameTypeID { return @1; }
- (BOOL)hasContent { return NO; }

- (nonnull instancetype)initWithSecret:(nonnull RMQLongstr *)secret
reason:(nonnull RMQShortstr *)reason {
self = [super init];
if (self) {
self.secret = secret;
self.reason = reason;
self.payloadArguments = @[self.secret,
self.reason];
}
return self;
}

- (instancetype)initWithDecodedFrame:(NSArray *)frame {
self = [super init];
if (self) {
self.secret = ((RMQLongstr *)frame[0]);
self.reason = ((RMQShortstr *)frame[1]);
self.payloadArguments = @[self.secret,
self.reason];
}
return self;
}

- (NSData *)amqEncoded {
NSMutableData *encoded = [NSMutableData new];
[encoded appendData:[[RMQShort alloc] init:self.classID.integerValue].amqEncoded];
[encoded appendData:[[RMQShort alloc] init:self.methodID.integerValue].amqEncoded];
for (id<RMQEncodable>arg in self.payloadArguments) {
[encoded appendData:arg.amqEncoded];
}
return encoded;
}

@end

@interface RMQConnectionUpdateSecretOk ()
@property (nonatomic, readwrite) NSArray *payloadArguments;
@property (nonatomic, readwrite) BOOL hasContent;
@end

@implementation RMQConnectionUpdateSecretOk

+ (NSArray *)propertyClasses {
return @[];
}
- (NSNumber *)classID { return @10; }
- (NSNumber *)methodID { return @71; }
- (Class)syncResponse { return nil; }
- (NSNumber *)frameTypeID { return @1; }
- (BOOL)hasContent { return NO; }


- (instancetype)initWithDecodedFrame:(NSArray *)frame {
self = [super init];
if (self) {
Expand Down
26 changes: 26 additions & 0 deletions RMQClientTests/ConnectionUpdateSecretTest.swift
@@ -0,0 +1,26 @@
//
// ConnectionUpdateSecretTest.swift
// RMQClientTests
//
// Created by Andrew Urban on 22.02.2024.
// Copyright © 2024 VMware. All rights reserved.
//

import XCTest

final class ConnectionUpdateSecretTest: XCTestCase {

func testSendsUpdateSecretMethod() {
let (transport, q, conn, _) = ConnectionWithFakesHelper.connectionAfterHandshake()

let secret = "someSecret"
let reason = "some test reason"

conn.updateSecret(secret, reason: reason);

try? q.step()

transport.assertClientSentMethod(MethodFixtures.connectionUpdateSecret(secret, reason: reason), channelNumber: 0)
}

}
5 changes: 5 additions & 0 deletions RMQClientTests/MethodFixtures.swift
Expand Up @@ -214,6 +214,11 @@ class MethodFixtures {
static func connectionTuneOk() -> RMQConnectionTuneOk {
return RMQConnectionTuneOk(channelMax: RMQShort(65535), frameMax: RMQLong(RMQFrameMax), heartbeat: RMQShort(60))
}

static func connectionUpdateSecret(_ secret: String,
reason: String) -> RMQConnectionUpdateSecret {
return RMQConnectionUpdateSecret(secret: RMQLongstr(secret), reason: RMQShortstr(reason))
}

static func exchangeBind(_ source: String, destination: String, routingKey: String) -> RMQExchangeBind {
return RMQExchangeBind(destination: destination, source: source, routingKey: routingKey)
Expand Down
30 changes: 30 additions & 0 deletions codegen/amqp0-9-1.extended.xml
Expand Up @@ -4,6 +4,7 @@
WARNING: Modified from the official 0-9-1 specification XML by
the addition of:
confirm.select and confirm.select-ok,
connection.update-secret and connection.update-secret-ok,
exchange.bind and exchange.bind-ok,
exchange.unbind and exchange.unbind-ok,
basic.nack,
Expand Down Expand Up @@ -914,6 +915,35 @@
<chassis name = "server" implement = "MUST"/>
<chassis name = "client" implement = "MUST"/>
</method>

<method name = "update-secret" synchronous = "1" index = "70" label = "update secret">
<doc>
This method updates the secret used to authenticate this connection. It is used when secrets have an expiration date and need to be renewed, like OAuth 2 tokens.
</doc>

<chassis name = "client" implement = "MUST" />
<response name = "update-secret-ok" />

<field name = "secret" domain = "longstr">
<doc>
The new secret.
</doc>
</field>

<field name = "reason" domain = "shortstr">
<doc>
The reason for the secret update.
</doc>
</field>
</method>

<method name = "update-secret-ok" synchronous = "1" index = "71" label = "update secret response">
<doc>
This method confirms the updated secret is valid.
</doc>
<chassis name = "server" implement = "MUST" />
</method>

</class>

<!-- == CHANNEL ========================================================== -->
Expand Down
14 changes: 1 addition & 13 deletions docker/Dockerfile
@@ -1,16 +1,4 @@
FROM ubuntu:18.04

RUN apt-get update -y
RUN apt-get install -y gnupg2 wget
RUN wget -O - "https://github.com/rabbitmq/signing-keys/releases/download/2.0/rabbitmq-release-signing-key.asc" | apt-key add -

COPY apt/sources.list.d/bintray.rabbitmq.list /etc/apt/sources.list.d/bintray.rabbitmq.list
COPY apt/preferences.d/erlang /etc/apt/preferences.d/erlang

RUN apt-get update -y

RUN apt-get upgrade -y && \
apt-get install -y rabbitmq-server
FROM rabbitmq:3.12-management

COPY docker-entrypoint.sh /
COPY certificates/*.pem /etc/rabbitmq/
Expand Down
3 changes: 0 additions & 3 deletions docker/apt/preferences.d/erlang

This file was deleted.

2 changes: 0 additions & 2 deletions docker/apt/sources.list.d/bintray.rabbitmq.list

This file was deleted.